# NQD developer documentation Make the money part easier. Learn how to connect your tools to NQD with clear guides and API references. ## Discovery - [Docs home](https://docs.nqd.app/v1) - [Full documentation context](https://docs.nqd.app/llms-full.txt) - [OpenAPI contract](https://docs.nqd.app/openapi.json) - [Sitemap](https://docs.nqd.app/sitemap.xml) - [Docs README](https://docs.nqd.app/v1/README.md) - [API reference README](https://docs.nqd.app/v1/reference/README.md) ## Guides - [NQD API getting started](https://docs.nqd.app/v1/guides/getting-started): Authenticate, select a workspace, and make your first guarded API request. - [NQD API authentication](https://docs.nqd.app/v1/guides/authentication): Use bearer credentials for the API and the shared browser session for Dash. - [NQD API workspaces and scopes](https://docs.nqd.app/v1/guides/workspaces): Select one verified workspace for each workspace-scoped request. - [NQD financial sources and cash Transactions](https://docs.nqd.app/v1/guides/financial-sources): Distinguish Invoice, Income, Expense, Payout, and Asset sources from the cash Transactions recorded against them. - [NQD API queries and field semantics](https://docs.nqd.app/v1/guides/queries): Use one Core-owned query vocabulary across HTTP, dashboard reads, and generated client help. - [NQD API errors and request IDs](https://docs.nqd.app/v1/guides/errors): Every failed request returns a safe error object with a request ID. - [NQD API limits and retries](https://docs.nqd.app/v1/guides/limits): Understand request allowances, plan limits, and when a retry is safe. - [NQD API integrations and webhooks](https://docs.nqd.app/v1/guides/integrations): Manage API keys, signed webhooks, delivery attempts, and activity logs from Dash or the workspace-scoped API. - [NQD CLI installation and commands](https://docs.nqd.app/v1/guides/cli): Install nqd, authenticate with OAuth or an API key, and manage NQD resources with native commands. - [NQD MCP setup and resource operations](https://docs.nqd.app/v1/guides/mcp): Use NQD's Streamable HTTP MCP server with resource-bound OAuth or API-key credentials. ## Finance source model - [NQD financial sources and cash Transactions](https://docs.nqd.app/v1/guides/financial-sources) - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Entries are reusable priced units for products, services, plans, or other calculable lines. Their amount is quantity multiplied by the net unit price; Entry prices exclude VAT. Applied Entries keep saved values independent from later catalog edits. - Modifiers change a targeted Entry or the whole source with supported fixed or percentage increases/decreases. Applied modifiers preserve their ordered target and value snapshots. NQD does not support arbitrary multiplication or division modifiers. - For bank statements, match each movement to an existing source or Transaction. Ask for its purpose when the movement is ambiguous; do not classify every debit as an Expense. ## API reference - [api-keys](https://docs.nqd.app/v1/reference/api-keys): 3 operations - [GET /v1/api-keys](https://docs.nqd.app/v1/reference/api-keys/list) - [POST /v1/api-keys](https://docs.nqd.app/v1/reference/api-keys/create) - [DELETE /v1/api-keys/{apiKeyId}](https://docs.nqd.app/v1/reference/api-keys/delete) - [assets](https://docs.nqd.app/v1/reference/assets): 17 operations - [GET /v1/assets](https://docs.nqd.app/v1/reference/assets/list) - [GET /v1/assets/{assetId}](https://docs.nqd.app/v1/reference/assets/retrieve) - [POST /v1/assets](https://docs.nqd.app/v1/reference/assets/create) - [PUT /v1/assets/{assetId}](https://docs.nqd.app/v1/reference/assets/upsert) - [PUT /v1/assets](https://docs.nqd.app/v1/reference/assets/bulk-upsert) - [GET /v1/assets/{assetId}/entries](https://docs.nqd.app/v1/reference/assets/entries/list) - [POST /v1/assets/{assetId}/entries](https://docs.nqd.app/v1/reference/assets/entries/create) - [PATCH /v1/assets/{assetId}/entries/{entryId}](https://docs.nqd.app/v1/reference/assets/entries/update) - [DELETE /v1/assets/{assetId}/entries/{entryId}](https://docs.nqd.app/v1/reference/assets/entries/delete) - [PUT /v1/assets/{assetId}/entries/reorder](https://docs.nqd.app/v1/reference/assets/entries/reorder/upsert) - [GET /v1/assets/{assetId}/modifiers](https://docs.nqd.app/v1/reference/assets/modifiers/list) - [POST /v1/assets/{assetId}/modifiers](https://docs.nqd.app/v1/reference/assets/modifiers/create) - [PATCH /v1/assets/{assetId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/assets/modifiers/update) - [DELETE /v1/assets/{assetId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/assets/modifiers/delete) - [PUT /v1/assets/{assetId}/modifiers/reorder](https://docs.nqd.app/v1/reference/assets/modifiers/reorder/upsert) - [GET /v1/assets/{sourceId}/transactions](https://docs.nqd.app/v1/reference/assets/transactions/list) - [POST /v1/assets/{sourceId}/transactions](https://docs.nqd.app/v1/reference/assets/transactions/create) - [authentication](https://docs.nqd.app/v1/reference/authentication): 2 operations - [POST /v1/email/challenges](https://docs.nqd.app/v1/reference/authentication/email/challenge) - [POST /v1/email/verifications](https://docs.nqd.app/v1/reference/authentication/email/verify) - [bank-accounts](https://docs.nqd.app/v1/reference/bank-accounts): 6 operations - [GET /v1/bank-accounts](https://docs.nqd.app/v1/reference/bank-accounts/list) - [POST /v1/bank-accounts](https://docs.nqd.app/v1/reference/bank-accounts/create) - [PUT /v1/bank-accounts/{bankAccountId}](https://docs.nqd.app/v1/reference/bank-accounts/upsert) - [DELETE /v1/bank-accounts/{bankAccountId}](https://docs.nqd.app/v1/reference/bank-accounts/delete) - [PUT /v1/bank-accounts](https://docs.nqd.app/v1/reference/bank-accounts/bulk-upsert) - [PUT /v1/bank-accounts/defaults](https://docs.nqd.app/v1/reference/bank-accounts/defaults/set) - [checkouts](https://docs.nqd.app/v1/reference/checkouts): 1 operations - [POST /v1/checkouts](https://docs.nqd.app/v1/reference/checkouts/create) - [clients](https://docs.nqd.app/v1/reference/clients): 9 operations - [GET /v1/clients](https://docs.nqd.app/v1/reference/clients/list) - [GET /v1/clients/{clientId}](https://docs.nqd.app/v1/reference/clients/retrieve) - [POST /v1/clients](https://docs.nqd.app/v1/reference/clients/create) - [PUT /v1/clients/{clientId}](https://docs.nqd.app/v1/reference/clients/upsert) - [DELETE /v1/clients/{clientId}](https://docs.nqd.app/v1/reference/clients/delete) - [PUT /v1/clients](https://docs.nqd.app/v1/reference/clients/bulk-upsert) - [GET /v1/clients/{clientId}/contacts](https://docs.nqd.app/v1/reference/clients/contacts/list) - [POST /v1/clients/{clientId}/contacts/{contactId}](https://docs.nqd.app/v1/reference/clients/contacts/create) - [DELETE /v1/clients/{clientId}/contacts/{contactId}](https://docs.nqd.app/v1/reference/clients/contacts/delete) - [contacts](https://docs.nqd.app/v1/reference/contacts): 6 operations - [GET /v1/contacts](https://docs.nqd.app/v1/reference/contacts/list) - [GET /v1/contacts/{contactId}](https://docs.nqd.app/v1/reference/contacts/retrieve) - [POST /v1/contacts](https://docs.nqd.app/v1/reference/contacts/create) - [PUT /v1/contacts/{contactId}](https://docs.nqd.app/v1/reference/contacts/upsert) - [DELETE /v1/contacts/{contactId}](https://docs.nqd.app/v1/reference/contacts/delete) - [PUT /v1/contacts](https://docs.nqd.app/v1/reference/contacts/bulk-upsert) - [currencies](https://docs.nqd.app/v1/reference/currencies): 7 operations - [GET /v1/currencies](https://docs.nqd.app/v1/reference/currencies/list) - [GET /v1/currencies/{currencyId}](https://docs.nqd.app/v1/reference/currencies/retrieve) - [POST /v1/currencies](https://docs.nqd.app/v1/reference/currencies/create) - [PUT /v1/currencies/{currencyId}](https://docs.nqd.app/v1/reference/currencies/upsert) - [DELETE /v1/currencies/{currencyId}](https://docs.nqd.app/v1/reference/currencies/delete) - [PUT /v1/currencies](https://docs.nqd.app/v1/reference/currencies/bulk-upsert) - [PUT /v1/currencies/default](https://docs.nqd.app/v1/reference/currencies/set-default) - [entries](https://docs.nqd.app/v1/reference/entries): 6 operations - [GET /v1/entries](https://docs.nqd.app/v1/reference/entries/list) - [GET /v1/entries/{entryId}](https://docs.nqd.app/v1/reference/entries/retrieve) - [POST /v1/entries](https://docs.nqd.app/v1/reference/entries/create) - [PUT /v1/entries/{entryId}](https://docs.nqd.app/v1/reference/entries/upsert) - [DELETE /v1/entries/{entryId}](https://docs.nqd.app/v1/reference/entries/delete) - [PUT /v1/entries](https://docs.nqd.app/v1/reference/entries/bulk-upsert) - [expenses](https://docs.nqd.app/v1/reference/expenses): 18 operations - [GET /v1/expenses](https://docs.nqd.app/v1/reference/expenses/list) - [GET /v1/expenses/{expenseId}](https://docs.nqd.app/v1/reference/expenses/retrieve) - [POST /v1/expenses](https://docs.nqd.app/v1/reference/expenses/create) - [PUT /v1/expenses/{expenseId}](https://docs.nqd.app/v1/reference/expenses/upsert) - [DELETE /v1/expenses/{expenseId}](https://docs.nqd.app/v1/reference/expenses/delete) - [PUT /v1/expenses](https://docs.nqd.app/v1/reference/expenses/bulk-upsert) - [GET /v1/expenses/{expenseId}/entries](https://docs.nqd.app/v1/reference/expenses/entries/list) - [POST /v1/expenses/{expenseId}/entries](https://docs.nqd.app/v1/reference/expenses/entries/create) - [PATCH /v1/expenses/{expenseId}/entries/{entryId}](https://docs.nqd.app/v1/reference/expenses/entries/update) - [DELETE /v1/expenses/{expenseId}/entries/{entryId}](https://docs.nqd.app/v1/reference/expenses/entries/delete) - [PUT /v1/expenses/{expenseId}/entries/reorder](https://docs.nqd.app/v1/reference/expenses/entries/reorder/upsert) - [GET /v1/expenses/{expenseId}/modifiers](https://docs.nqd.app/v1/reference/expenses/modifiers/list) - [POST /v1/expenses/{expenseId}/modifiers](https://docs.nqd.app/v1/reference/expenses/modifiers/create) - [PATCH /v1/expenses/{expenseId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/expenses/modifiers/update) - [DELETE /v1/expenses/{expenseId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/expenses/modifiers/delete) - [PUT /v1/expenses/{expenseId}/modifiers/reorder](https://docs.nqd.app/v1/reference/expenses/modifiers/reorder/upsert) - [GET /v1/expenses/{sourceId}/transactions](https://docs.nqd.app/v1/reference/expenses/transactions/list) - [POST /v1/expenses/{sourceId}/transactions](https://docs.nqd.app/v1/reference/expenses/transactions/create) - [expense-templates](https://docs.nqd.app/v1/reference/expenses/templates): 15 operations - [GET /v1/expenses/templates](https://docs.nqd.app/v1/reference/expenses/templates/list) - [POST /v1/expenses/templates](https://docs.nqd.app/v1/reference/expenses/templates/create) - [PUT /v1/expenses/templates/{templateId}](https://docs.nqd.app/v1/reference/expenses/templates/upsert) - [DELETE /v1/expenses/templates/{templateId}](https://docs.nqd.app/v1/reference/expenses/templates/delete) - [PUT /v1/expenses/templates](https://docs.nqd.app/v1/reference/expenses/templates/bulk-upsert) - [GET /v1/expenses/templates/{templateId}/entries](https://docs.nqd.app/v1/reference/expenses/templates/entries/list) - [POST /v1/expenses/templates/{templateId}/entries](https://docs.nqd.app/v1/reference/expenses/templates/entries/create) - [PATCH /v1/expenses/templates/{templateId}/entries/{entryId}](https://docs.nqd.app/v1/reference/expenses/templates/entries/update) - [DELETE /v1/expenses/templates/{templateId}/entries/{entryId}](https://docs.nqd.app/v1/reference/expenses/templates/entries/delete) - [PUT /v1/expenses/templates/{templateId}/entries/reorder](https://docs.nqd.app/v1/reference/expenses/templates/entries/reorder/upsert) - [GET /v1/expenses/templates/{templateId}/modifiers](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/list) - [POST /v1/expenses/templates/{templateId}/modifiers](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/create) - [PATCH /v1/expenses/templates/{templateId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/update) - [DELETE /v1/expenses/templates/{templateId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/delete) - [PUT /v1/expenses/templates/{templateId}/modifiers/reorder](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/reorder/upsert) - [income](https://docs.nqd.app/v1/reference/income): 18 operations - [GET /v1/income](https://docs.nqd.app/v1/reference/income/list) - [GET /v1/income/{incomeId}](https://docs.nqd.app/v1/reference/income/retrieve) - [POST /v1/income](https://docs.nqd.app/v1/reference/income/create) - [PUT /v1/income/{incomeId}](https://docs.nqd.app/v1/reference/income/upsert) - [DELETE /v1/income/{incomeId}](https://docs.nqd.app/v1/reference/income/delete) - [PUT /v1/income](https://docs.nqd.app/v1/reference/income/bulk-upsert) - [GET /v1/income/{incomeId}/entries](https://docs.nqd.app/v1/reference/income/entries/list) - [POST /v1/income/{incomeId}/entries](https://docs.nqd.app/v1/reference/income/entries/create) - [PATCH /v1/income/{incomeId}/entries/{entryId}](https://docs.nqd.app/v1/reference/income/entries/update) - [DELETE /v1/income/{incomeId}/entries/{entryId}](https://docs.nqd.app/v1/reference/income/entries/delete) - [PUT /v1/income/{incomeId}/entries/reorder](https://docs.nqd.app/v1/reference/income/entries/reorder/upsert) - [GET /v1/income/{incomeId}/modifiers](https://docs.nqd.app/v1/reference/income/modifiers/list) - [POST /v1/income/{incomeId}/modifiers](https://docs.nqd.app/v1/reference/income/modifiers/create) - [PATCH /v1/income/{incomeId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/income/modifiers/update) - [DELETE /v1/income/{incomeId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/income/modifiers/delete) - [PUT /v1/income/{incomeId}/modifiers/reorder](https://docs.nqd.app/v1/reference/income/modifiers/reorder/upsert) - [GET /v1/income/{sourceId}/transactions](https://docs.nqd.app/v1/reference/income/transactions/list) - [POST /v1/income/{sourceId}/transactions](https://docs.nqd.app/v1/reference/income/transactions/create) - [invitations](https://docs.nqd.app/v1/reference/invitations): 5 operations - [POST /v1/invitations](https://docs.nqd.app/v1/reference/invitations/create) - [DELETE /v1/invitations/{inviteId}](https://docs.nqd.app/v1/reference/invitations/delete) - [POST /v1/invitations/{inviteId}/redeliveries](https://docs.nqd.app/v1/reference/invitations/redeliveries/create) - [POST /v1/invitations/acceptances](https://docs.nqd.app/v1/reference/invitations/acceptances/create) - [GET /v1/invitations/pending](https://docs.nqd.app/v1/reference/invitations/pending) - [invoices](https://docs.nqd.app/v1/reference/invoices): 18 operations - [GET /v1/invoices](https://docs.nqd.app/v1/reference/invoices/list) - [GET /v1/invoices/{invoiceId}](https://docs.nqd.app/v1/reference/invoices/retrieve) - [POST /v1/invoices](https://docs.nqd.app/v1/reference/invoices/create) - [PUT /v1/invoices/{invoiceId}](https://docs.nqd.app/v1/reference/invoices/upsert) - [DELETE /v1/invoices/{invoiceId}](https://docs.nqd.app/v1/reference/invoices/delete) - [PUT /v1/invoices](https://docs.nqd.app/v1/reference/invoices/bulk-upsert) - [GET /v1/invoices/{invoiceId}/entries](https://docs.nqd.app/v1/reference/invoices/entries/list) - [POST /v1/invoices/{invoiceId}/entries](https://docs.nqd.app/v1/reference/invoices/entries/create) - [PATCH /v1/invoices/{invoiceId}/entries/{entryId}](https://docs.nqd.app/v1/reference/invoices/entries/update) - [DELETE /v1/invoices/{invoiceId}/entries/{entryId}](https://docs.nqd.app/v1/reference/invoices/entries/delete) - [PUT /v1/invoices/{invoiceId}/entries/reorder](https://docs.nqd.app/v1/reference/invoices/entries/reorder/upsert) - [GET /v1/invoices/{invoiceId}/modifiers](https://docs.nqd.app/v1/reference/invoices/modifiers/list) - [POST /v1/invoices/{invoiceId}/modifiers](https://docs.nqd.app/v1/reference/invoices/modifiers/create) - [PATCH /v1/invoices/{invoiceId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/invoices/modifiers/update) - [DELETE /v1/invoices/{invoiceId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/invoices/modifiers/delete) - [PUT /v1/invoices/{invoiceId}/modifiers/reorder](https://docs.nqd.app/v1/reference/invoices/modifiers/reorder/upsert) - [GET /v1/invoices/{sourceId}/transactions](https://docs.nqd.app/v1/reference/invoices/transactions/list) - [POST /v1/invoices/{sourceId}/transactions](https://docs.nqd.app/v1/reference/invoices/transactions/create) - [invoice-templates](https://docs.nqd.app/v1/reference/invoices/templates): 15 operations - [GET /v1/invoices/templates](https://docs.nqd.app/v1/reference/invoices/templates/list) - [POST /v1/invoices/templates](https://docs.nqd.app/v1/reference/invoices/templates/create) - [PUT /v1/invoices/templates/{templateId}](https://docs.nqd.app/v1/reference/invoices/templates/upsert) - [DELETE /v1/invoices/templates/{templateId}](https://docs.nqd.app/v1/reference/invoices/templates/delete) - [PUT /v1/invoices/templates](https://docs.nqd.app/v1/reference/invoices/templates/bulk-upsert) - [GET /v1/invoices/templates/{templateId}/entries](https://docs.nqd.app/v1/reference/invoices/templates/entries/list) - [POST /v1/invoices/templates/{templateId}/entries](https://docs.nqd.app/v1/reference/invoices/templates/entries/create) - [PATCH /v1/invoices/templates/{templateId}/entries/{entryId}](https://docs.nqd.app/v1/reference/invoices/templates/entries/update) - [DELETE /v1/invoices/templates/{templateId}/entries/{entryId}](https://docs.nqd.app/v1/reference/invoices/templates/entries/delete) - [PUT /v1/invoices/templates/{templateId}/entries/reorder](https://docs.nqd.app/v1/reference/invoices/templates/entries/reorder/upsert) - [GET /v1/invoices/templates/{templateId}/modifiers](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/list) - [POST /v1/invoices/templates/{templateId}/modifiers](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/create) - [PATCH /v1/invoices/templates/{templateId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/update) - [DELETE /v1/invoices/templates/{templateId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/delete) - [PUT /v1/invoices/templates/{templateId}/modifiers/reorder](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/reorder/upsert) - [logs](https://docs.nqd.app/v1/reference/logs): 1 operations - [GET /v1/logs](https://docs.nqd.app/v1/reference/logs/list) - [modifiers](https://docs.nqd.app/v1/reference/modifiers): 7 operations - [GET /v1/modifiers](https://docs.nqd.app/v1/reference/modifiers/list) - [GET /v1/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/modifiers/retrieve) - [POST /v1/modifiers](https://docs.nqd.app/v1/reference/modifiers/create) - [PUT /v1/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/modifiers/upsert) - [DELETE /v1/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/modifiers/delete) - [PUT /v1/modifiers](https://docs.nqd.app/v1/reference/modifiers/bulk-upsert) - [PUT /v1/modifiers/tax](https://docs.nqd.app/v1/reference/modifiers/set-tax) - [participants](https://docs.nqd.app/v1/reference/participants): 3 operations - [GET /v1/participants](https://docs.nqd.app/v1/reference/participants/list) - [DELETE /v1/participants/{profileId}](https://docs.nqd.app/v1/reference/participants/delete) - [PUT /v1/participants/{profileId}/role](https://docs.nqd.app/v1/reference/participants/role/upsert) - [payouts](https://docs.nqd.app/v1/reference/payouts): 18 operations - [GET /v1/payouts](https://docs.nqd.app/v1/reference/payouts/list) - [GET /v1/payouts/{payoutId}](https://docs.nqd.app/v1/reference/payouts/retrieve) - [POST /v1/payouts](https://docs.nqd.app/v1/reference/payouts/create) - [PUT /v1/payouts/{payoutId}](https://docs.nqd.app/v1/reference/payouts/upsert) - [DELETE /v1/payouts/{payoutId}](https://docs.nqd.app/v1/reference/payouts/delete) - [PUT /v1/payouts](https://docs.nqd.app/v1/reference/payouts/bulk-upsert) - [GET /v1/payouts/{payoutId}/entries](https://docs.nqd.app/v1/reference/payouts/entries/list) - [POST /v1/payouts/{payoutId}/entries](https://docs.nqd.app/v1/reference/payouts/entries/create) - [PATCH /v1/payouts/{payoutId}/entries/{entryId}](https://docs.nqd.app/v1/reference/payouts/entries/update) - [DELETE /v1/payouts/{payoutId}/entries/{entryId}](https://docs.nqd.app/v1/reference/payouts/entries/delete) - [PUT /v1/payouts/{payoutId}/entries/reorder](https://docs.nqd.app/v1/reference/payouts/entries/reorder/upsert) - [GET /v1/payouts/{payoutId}/modifiers](https://docs.nqd.app/v1/reference/payouts/modifiers/list) - [POST /v1/payouts/{payoutId}/modifiers](https://docs.nqd.app/v1/reference/payouts/modifiers/create) - [PATCH /v1/payouts/{payoutId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/payouts/modifiers/update) - [DELETE /v1/payouts/{payoutId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/payouts/modifiers/delete) - [PUT /v1/payouts/{payoutId}/modifiers/reorder](https://docs.nqd.app/v1/reference/payouts/modifiers/reorder/upsert) - [GET /v1/payouts/{sourceId}/transactions](https://docs.nqd.app/v1/reference/payouts/transactions/list) - [POST /v1/payouts/{sourceId}/transactions](https://docs.nqd.app/v1/reference/payouts/transactions/create) - [payout-templates](https://docs.nqd.app/v1/reference/payouts/templates): 15 operations - [GET /v1/payouts/templates](https://docs.nqd.app/v1/reference/payouts/templates/list) - [POST /v1/payouts/templates](https://docs.nqd.app/v1/reference/payouts/templates/create) - [PUT /v1/payouts/templates/{templateId}](https://docs.nqd.app/v1/reference/payouts/templates/upsert) - [DELETE /v1/payouts/templates/{templateId}](https://docs.nqd.app/v1/reference/payouts/templates/delete) - [PUT /v1/payouts/templates](https://docs.nqd.app/v1/reference/payouts/templates/bulk-upsert) - [GET /v1/payouts/templates/{templateId}/entries](https://docs.nqd.app/v1/reference/payouts/templates/entries/list) - [POST /v1/payouts/templates/{templateId}/entries](https://docs.nqd.app/v1/reference/payouts/templates/entries/create) - [PATCH /v1/payouts/templates/{templateId}/entries/{entryId}](https://docs.nqd.app/v1/reference/payouts/templates/entries/update) - [DELETE /v1/payouts/templates/{templateId}/entries/{entryId}](https://docs.nqd.app/v1/reference/payouts/templates/entries/delete) - [PUT /v1/payouts/templates/{templateId}/entries/reorder](https://docs.nqd.app/v1/reference/payouts/templates/entries/reorder/upsert) - [GET /v1/payouts/templates/{templateId}/modifiers](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/list) - [POST /v1/payouts/templates/{templateId}/modifiers](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/create) - [PATCH /v1/payouts/templates/{templateId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/update) - [DELETE /v1/payouts/templates/{templateId}/modifiers/{modifierId}](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/delete) - [PUT /v1/payouts/templates/{templateId}/modifiers/reorder](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/reorder/upsert) - [plans](https://docs.nqd.app/v1/reference/plans): 1 operations - [GET /v1/plans](https://docs.nqd.app/v1/reference/plans/list) - [preferences](https://docs.nqd.app/v1/reference/preferences): 1 operations - [PUT /v1/preferences](https://docs.nqd.app/v1/reference/preferences/upsert) - [profile](https://docs.nqd.app/v1/reference/profile): 4 operations - [GET /v1/profile](https://docs.nqd.app/v1/reference/profile/retrieve) - [POST /v1/profile](https://docs.nqd.app/v1/reference/profile/create) - [PUT /v1/profile](https://docs.nqd.app/v1/reference/profile/upsert) - [POST /v1/profile/avatar-uploads](https://docs.nqd.app/v1/reference/profile/avatar-uploads/create) - [profile-preferences](https://docs.nqd.app/v1/reference/profile/preferences): 2 operations - [GET /v1/profile/preferences](https://docs.nqd.app/v1/reference/profile/preferences/list) - [PUT /v1/profile/preferences](https://docs.nqd.app/v1/reference/profile/preferences/upsert) - [projects](https://docs.nqd.app/v1/reference/projects): 6 operations - [GET /v1/projects](https://docs.nqd.app/v1/reference/projects/list) - [GET /v1/projects/{projectId}](https://docs.nqd.app/v1/reference/projects/retrieve) - [POST /v1/projects](https://docs.nqd.app/v1/reference/projects/create) - [PUT /v1/projects/{projectId}](https://docs.nqd.app/v1/reference/projects/upsert) - [DELETE /v1/projects/{projectId}](https://docs.nqd.app/v1/reference/projects/delete) - [PUT /v1/projects](https://docs.nqd.app/v1/reference/projects/bulk-upsert) - [reports](https://docs.nqd.app/v1/reference/reports): 14 operations - [GET /v1/reports/balance-sheet](https://docs.nqd.app/v1/reference/reports/balance-sheet) - [GET /v1/reports/cash-flow](https://docs.nqd.app/v1/reference/reports/cash-flow) - [GET /v1/reports/cashbook](https://docs.nqd.app/v1/reference/reports/cashbook) - [GET /v1/reports/center](https://docs.nqd.app/v1/reference/reports/center) - [GET /v1/reports/income-statement](https://docs.nqd.app/v1/reference/reports/income-statement) - [GET /v1/reports/movements](https://docs.nqd.app/v1/reference/reports/movements) - [GET /v1/reports/overview](https://docs.nqd.app/v1/reference/reports/overview) - [GET /v1/reports/payables](https://docs.nqd.app/v1/reference/reports/payables) - [GET /v1/reports/profit-loss](https://docs.nqd.app/v1/reference/reports/profit-loss) - [GET /v1/reports/receivables](https://docs.nqd.app/v1/reference/reports/receivables) - [GET /v1/reports/statements](https://docs.nqd.app/v1/reference/reports/statements) - [GET /v1/reports/summary](https://docs.nqd.app/v1/reference/reports/summary) - [GET /v1/reports/tax-control](https://docs.nqd.app/v1/reference/reports/tax-control) - [GET /v1/reports/trial-balance](https://docs.nqd.app/v1/reference/reports/trial-balance) - [retention](https://docs.nqd.app/v1/reference/retention): 4 operations - [GET /v1/retention](https://docs.nqd.app/v1/reference/retention/retrieve) - [PUT /v1/retention](https://docs.nqd.app/v1/reference/retention/upsert) - [GET /v1/retention/preview](https://docs.nqd.app/v1/reference/retention/preview/retrieve) - [POST /v1/retention/prune](https://docs.nqd.app/v1/reference/retention/prune/create) - [settings](https://docs.nqd.app/v1/reference/settings): 3 operations - [GET /v1/settings](https://docs.nqd.app/v1/reference/settings/retrieve) - [PUT /v1/settings](https://docs.nqd.app/v1/reference/settings/upsert) - [POST /v1/settings/avatar-uploads](https://docs.nqd.app/v1/reference/settings/avatar-uploads/create) - [fiscal-year](https://docs.nqd.app/v1/reference/settings/fiscal-year): 1 operations - [PUT /v1/settings/fiscal-year](https://docs.nqd.app/v1/reference/settings/fiscal-year/upsert) - [payables](https://docs.nqd.app/v1/reference/settings/payables): 2 operations - [GET /v1/settings/payables](https://docs.nqd.app/v1/reference/settings/payables/list) - [PUT /v1/settings/payables](https://docs.nqd.app/v1/reference/settings/payables/upsert) - [tags](https://docs.nqd.app/v1/reference/tags): 6 operations - [GET /v1/tags](https://docs.nqd.app/v1/reference/tags/list) - [GET /v1/tags/{tagId}](https://docs.nqd.app/v1/reference/tags/retrieve) - [POST /v1/tags](https://docs.nqd.app/v1/reference/tags/create) - [PUT /v1/tags/{tagId}](https://docs.nqd.app/v1/reference/tags/upsert) - [DELETE /v1/tags/{tagId}](https://docs.nqd.app/v1/reference/tags/delete) - [PUT /v1/tags](https://docs.nqd.app/v1/reference/tags/bulk-upsert) - [transactions](https://docs.nqd.app/v1/reference/transactions): 3 operations - [GET /v1/transactions](https://docs.nqd.app/v1/reference/transactions/list) - [DELETE /v1/transactions/{transactionId}](https://docs.nqd.app/v1/reference/transactions/delete) - [PATCH /v1/transactions/{transactionId}](https://docs.nqd.app/v1/reference/transactions/update) - [units](https://docs.nqd.app/v1/reference/units): 6 operations - [GET /v1/units](https://docs.nqd.app/v1/reference/units/list) - [GET /v1/units/{code}](https://docs.nqd.app/v1/reference/units/retrieve) - [POST /v1/units](https://docs.nqd.app/v1/reference/units/create) - [PUT /v1/units/{code}](https://docs.nqd.app/v1/reference/units/upsert) - [DELETE /v1/units/{code}](https://docs.nqd.app/v1/reference/units/delete) - [PUT /v1/units](https://docs.nqd.app/v1/reference/units/bulk-upsert) - [usage](https://docs.nqd.app/v1/reference/usage): 1 operations - [GET /v1/usage](https://docs.nqd.app/v1/reference/usage/retrieve) - [vendors](https://docs.nqd.app/v1/reference/vendors): 9 operations - [GET /v1/vendors](https://docs.nqd.app/v1/reference/vendors/list) - [GET /v1/vendors/{vendorId}](https://docs.nqd.app/v1/reference/vendors/retrieve) - [POST /v1/vendors](https://docs.nqd.app/v1/reference/vendors/create) - [PUT /v1/vendors/{vendorId}](https://docs.nqd.app/v1/reference/vendors/upsert) - [DELETE /v1/vendors/{vendorId}](https://docs.nqd.app/v1/reference/vendors/delete) - [PUT /v1/vendors](https://docs.nqd.app/v1/reference/vendors/bulk-upsert) - [GET /v1/vendors/{vendorId}/contacts](https://docs.nqd.app/v1/reference/vendors/contacts/list) - [POST /v1/vendors/{vendorId}/contacts/{contactId}](https://docs.nqd.app/v1/reference/vendors/contacts/create) - [DELETE /v1/vendors/{vendorId}/contacts/{contactId}](https://docs.nqd.app/v1/reference/vendors/contacts/delete) - [webhooks](https://docs.nqd.app/v1/reference/webhooks): 11 operations - [GET /v1/webhooks](https://docs.nqd.app/v1/reference/webhooks/list) - [POST /v1/webhooks](https://docs.nqd.app/v1/reference/webhooks/create) - [PUT /v1/webhooks/{webhookId}](https://docs.nqd.app/v1/reference/webhooks/upsert) - [DELETE /v1/webhooks/{webhookId}](https://docs.nqd.app/v1/reference/webhooks/delete) - [GET /v1/webhooks/{webhookId}/deliveries](https://docs.nqd.app/v1/reference/webhooks/deliveries/list) - [POST /v1/webhooks/{webhookId}/deliveries/{logId}/retry](https://docs.nqd.app/v1/reference/webhooks/deliveries/retry) - [POST /v1/webhooks/{webhookId}/pause](https://docs.nqd.app/v1/reference/webhooks/pause) - [POST /v1/webhooks/{webhookId}/resume](https://docs.nqd.app/v1/reference/webhooks/resume) - [POST /v1/webhooks/{webhookId}/rotate](https://docs.nqd.app/v1/reference/webhooks/rotate) - [POST /v1/webhooks/{webhookId}/test](https://docs.nqd.app/v1/reference/webhooks/test) - [POST /v1/webhooks/{webhookId}/verify](https://docs.nqd.app/v1/reference/webhooks/verify) - [workspaces](https://docs.nqd.app/v1/reference/workspaces): 2 operations - [GET /v1/workspaces](https://docs.nqd.app/v1/reference/workspaces/list) - [POST /v1/workspaces](https://docs.nqd.app/v1/reference/workspaces/create) - [OpenAPI contract](https://docs.nqd.app/openapi.json) ## Guide content # NQD API getting started Authenticate, select a workspace, and make your first guarded API request. The developer credential flow authenticates your account; it does not create a profile, workspace, or bypass their limits. Read the [financial sources guide](/v1/guides/financial-sources) before importing bank movements. It explains when to create an Invoice, Income, Expense, Payout, or Asset, and when to record a cash Transaction against an existing source. Set the origins once for your shell. The local launcher uses port `1335`; production uses the origins configured for your deployment. ```bash export AUTH="http://auth.nqd.localhost:1335" export API="http://api.nqd.localhost:1335" export DASH="http://dash.nqd.localhost:1335" export DOCS="http://docs.nqd.localhost:1335" export MCP="http://mcp.nqd.localhost:1335" export CLI="http://cli.nqd.localhost:1335" ``` ## Local origins The canonical production origins are HTTPS subdomains configured by your deployment. Local development uses the shared HTTP origin configured by the launcher. The default registered origins are `auth`, `api`, `dash`, `web`, `docs`, `mcp`, and `cli` under `nqd.localhost:1335`. Resolve branch or fixture origins from the launcher instead of copying these defaults into a client. Use the [CLI guide](/v1/guides/cli) for the installed command and the [MCP guide](/v1/guides/mcp) for remote tool clients. ## 1. Request and verify a code Use your own email and the received code. These fictional examples never execute from Docs. ```bash curl "$AUTH/v1/email/challenges" \ --json '{"email":"developer@example.test"}' curl "$AUTH/v1/email/verifications" \ --json '{"email":"developer@example.test","code":"123456"}' ``` Verification returns `access_token`, `token_type: "bearer"`, and the provider's `expires_at` Unix seconds. Store the token securely as `$TOKEN`. No refresh token or Dash cookie is returned. Obtain a new OTP credential when it expires. ## 2. Discover workspaces ```bash curl "$API/v1/workspaces" -H "Authorization: Bearer $TOKEN" ``` Choose an ID from `data`. Store it as `$WORKSPACE`. Workspace discovery is identity-scoped and accepts no Workspace-Id header. ## 3. Read the catalog and payable settings ```bash curl "$API/v1/currencies?limit=25" \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" curl "$API/v1/entries?limit=25" \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" curl "$API/v1/modifiers?limit=25" \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" curl "$API/v1/settings/payables" \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" ``` The catalog responses return records in `data` and page metadata, including an opaque `page.nextCursor` when more records are available. Payable settings identify the workspace's current payable modifier. Use IDs returned by these resources when you create a financial record. Do not invent related records or put a Workspace ID in a Client field. Workspace-scoped bodies do not repeat `workspaceId`; the `Workspace-Id` header supplies that scope. Collection responses place arrays in `data`; single-resource responses place one object there. ## 4. Create a draft For a fictional Workspace with 15% VAT, save the following as `invoice.json`. Replace the Currency, Entry, and Modifier IDs with records from your Workspace. The Entry price is **100 net**, and the applied modifier supplies the VAT. Preserve decimal strings. The IDs below are illustrative; use the IDs returned by the catalog resources. ```json [ { "name": "Fictional consulting draft", "description": "Fictional example", "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "currencyId": "01ARZ3NDEKTSV4RRFFQ69G5FAV", "entries": [ { "id": "01ARZ3NDEKTSV4RRFFQ69G5FA7", "name": "Consulting", "description": "Fictional example", "quantity": "1", "unit": "hour", "pricePerUnit": "100" } ], "modifiers": [ { "id": "01ARZ3NDEKTSV4RRFFQ69G5FA9", "name": "VAT", "value": "15.00%" } ], "tags": [] } ] ``` Each POST body is an array of writable records. `currencyId`, `entries`, and `modifiers` are fields on each record. The response returns the created records in `data`; the request uses relationship IDs so the server can validate them against the workspace catalog. The example uses the standard `hour` catalog unit; use a unit returned by the units resource in your workspace. A modifier's `value` uses a trailing `%` for a percentage and a leading `-` for a decrease. Core applies the workspace's configured payable modifier as the tax rule when calculating totals. ```bash curl "$API/v1/invoices" -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" \ -H 'Content-Type: application/json' --data-binary @invoice.json ``` A successful create returns 201 and a `data` array because this resource create accepts a batch envelope. Follow the returned record ID with the same bearer and workspace headers. Read the [invoice reference](/v1/reference/invoices/list) before updating the invoice or posting payments. If a write's response is lost, reconcile the current source and transaction summary before retrying. Canonical page: [https://docs.nqd.app/v1/guides/getting-started](https://docs.nqd.app/v1/guides/getting-started) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD API authentication Use bearer credentials for the API and the shared browser session for Dash. Business requests use `Authorization: Bearer `. NQD verifies the credential and resolves membership on every request. Invalid or expired credentials return 401. Cookies never select API identity or workspace scope. `POST /v1/email/challenges` and `POST /v1/email/verifications` accept bounded JSON and do not use `Workspace-Id`. Verification returns an access token, bearer type, and expiration. It does not set a persistent session cookie. Browser sign-in uses Auth's `/signin`, `/signup`, and `/verify`, then hands off to Dash. Auth and Dash share the browser session cookie across their configured parent domain. These flows are not developer REST endpoints. Create API keys in Dash under **Settings → Integrations → API keys** or with the workspace-scoped API key endpoints. The secret appears once. Store it securely. Use OAuth when an interactive client needs delegated workspace access. NQD uses an authorization-code flow with S256 PKCE. The issuer binds each grant to the client, exact redirect URI, requested resource origin, workspace, and scopes. The authorization endpoints are on the configured Auth origin: ```text /.well-known/oauth-authorization-server /.well-known/oauth-protected-resource /oauth/register /oauth/authorize /oauth/token /oauth/revoke ``` The CLI uses a loopback callback and stores tokens in the native OS credential manager. The token response includes the consented `workspace_id`. Remote MCP clients discover the issuer from protected-resource metadata and send the resulting resource-bound access token in `Authorization: Bearer`. The API and MCP reject a token issued for another resource. Core checks the active grant, workspace membership, token expiry, and operation scope on every request. OAuth grants are workspace-bound. Workspace operations require the selected workspace. `account.context` is the sole subject read and is filtered to that workspace; global profile and workspace mutations are denied through the grant. The shared scope vocabulary currently contains `read` and `write`. Clients request only the scopes they need, and the consent screen and resource server enforce the same values. Refresh tokens rotate. Reuse of a rotated refresh token revokes its token family. Revoking a grant or removing workspace membership takes effect on the next guarded operation. Never put credentials in URLs or resource bodies. See the [challenge endpoint](/v1/reference/authentication/email/challenge) and [verification endpoint](/v1/reference/authentication/email/verify) in the generated authentication reference. Canonical page: [https://docs.nqd.app/v1/guides/authentication](https://docs.nqd.app/v1/guides/authentication) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD API workspaces and scopes Select one verified workspace for each workspace-scoped request. `GET /v1/workspaces` lists the account's memberships. Identity-scoped calls omit `Workspace-Id`. Every workspace-scoped request, including GET and DELETE, sends one `Workspace-Id` header. The header selects a scope; it grants no access. Missing, malformed, duplicate, or comma-joined selectors return 400. A revoked membership returns 403. Resource IDs and filters stay inside the selected workspace. The `/v1` path selects the API contract. It is the only version selector. API URLs do not repeat the workspace as a path segment; `Workspace-Id` supplies that scope. Resource bodies contain authored fields and relationships. Do not repeat the selected workspace in a body: `Workspace-Id` is the scope for the request. No request chooses a first workspace automatically. For ordinary workspace-owned records, a null `clientId` means the current Workspace. Contacts can carry nullable `clientId` and `vendorId` relationships: both null means the Workspace owns the contact, while either relationship identifies its associated party. When both are supplied, they must resolve to the same party. Do not manufacture a Client to represent the Workspace. Payout Contacts identify recipients independently of a Project's Client. Caches should include principal, workspace, version, resource, and query. Discard cached data when scope changes. Canonical page: [https://docs.nqd.app/v1/guides/workspaces](https://docs.nqd.app/v1/guides/workspaces) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD financial sources and cash Transactions Distinguish Invoice, Income, Expense, Payout, and Asset sources from the cash Transactions recorded against them. NQD separates financial sources from the cash Transactions recorded against them. A source describes what the money or wealth represents. A Transaction records an actual cash movement. Sources can be unpaid or partially paid. ## Sources - **Invoice:** Incoming service source. Use Client and Project for the service context, and Entries for the priced units. Post one or more Transactions as customers pay. - **Income:** Other incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or another standalone receipt. A buyer Client is optional. - **Expense:** Outgoing payment source for a Vendor's service. A Vendor can be an individual or a company. Client and Project are optional. A null Client means the current Workspace. - **Payout:** Outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional. A null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role decides whether the source is an Expense or Payout. - **Asset:** Non-cash holding. Its acquisition may have a separate cash Transaction. The holding and the acquisition event stay distinct. Do not create a placeholder Client for the Workspace. Leave `clientId` null and resolve Workspace ownership at runtime. ## Entries and Modifiers Entries are reusable priced units for products, services, plans, or other calculable lines. An Entry amount is quantity multiplied by its net unit price; Entry prices exclude VAT. An applied Entry keeps its saved values even when its catalog definition changes. Modifiers change one Entry or the whole source. NQD supports signed fixed amounts and percentages, including increases and decreases. Applied modifiers preserve their ordered target and value snapshots. It does not support arbitrary multiplication or division modifiers. A modifier with an `entryIndex` belongs to that Entry. A null `entryIndex` applies to the source. ## Bank statement classification Use the statement to find cash Transactions and match them to existing sources before creating anything. Ask for the purpose of a movement when its description is ambiguous. A debit is not automatically an Expense. A transfer, withdrawal, refund, loan, investment, or personal movement needs its own classification. When a payment settles an existing Invoice, Expense, or Payout, record a Transaction against that source instead of creating a duplicate source. Keep the statement's payment date and amount as the cash event details. Canonical page: [https://docs.nqd.app/v1/guides/financial-sources](https://docs.nqd.app/v1/guides/financial-sources) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD API queries and field semantics Use one Core-owned query vocabulary across HTTP, dashboard reads, and generated client help. Query-capable GET endpoints use `filter`, `select`, `order`, `limit`, `cursor`, `count`, and resource-approved `search`. Each operation exposes only the fields declared by Core. Writes use JSON bodies; DELETE uses path and headers. Unknown fields and oversized payloads are rejected. Collection reads return a `data` array, even when a filter matches one record. Single-record reads return one object in `data`. POST and PUT return arrays for batch resource writes; commands that operate on one record return an object. A successful 204 response has no body. Each endpoint's response schema defines its exact shape. Paginated collections use `limit` and an opaque `cursor`. The response contains `data` and `page.nextCursor`/`page.hasMore`. The default limit is 25; each resource declares its maximum. `count=exact` is available only where the resource supports it. Use filter expressions such as `filter[status]=in.(pending,paid)` and `filter[createdAt]=gte.2026-01-01T00:00:00Z`. Select fields with `select=id,name,currency`; select declared relations with `select=id,name,client(id,name)`. Order with `order=createdAt.desc,id.desc`. No SQL, arbitrary expressions, or undeclared relations are accepted. Directories are Core snapshots. They expose only declared fields, operators, and relations. Financial filters use runtime totals, modifiers, and effective transactions. Recurring templates describe schedules; the recurrence workflow creates due records. Money is an exact decimal string. Database projections may retain trailing zeroes; do not convert authored values to floating-point numbers. Entry prices exclude VAT. Report/chart numbers keep their existing projection precision. Timestamps use the generated ISO contract; preserve all digits, including microseconds for stale-edit checks. `null` clears a nullable field. If a field is required and nullable, include it with `null` when no value applies. Omit a field only when the schema marks it optional. POST and PUT use the writable resource representation. Send relationship IDs from the matching catalog or party resource. Canonical page: [https://docs.nqd.app/v1/guides/queries](https://docs.nqd.app/v1/guides/queries) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD API errors and request IDs Every failed request returns a safe error object with a request ID. Resource errors have an error object containing code, message, and requestId. Invalid input may also include `error.details.issues`, each with a field path and safe validation reason. Responses omit stack traces, SQL, provider responses, and credentials. Use requestId when reporting a failure. When the transport supplies `x-request-id`, it identifies the same request and should be retained with the error. | Status | Code | Meaning | | --- | --- | --- | | 400 | invalid_input | Invalid scope, query, body, or domain input | | 400 | query_invalid | Query field, operator, projection, cursor, or limit is unsupported; details.issues identifies the rejected path | | 401 | unauthenticated | Missing or invalid bearer; WWW-Authenticate is Bearer | | 403 | forbidden | Current membership/permission denied | | 403 | plan_limit | Existing finance/seat/entitlement limit denied | | 403 | cors_forbidden | Origin is outside the configured API caller list | | 404 | not_found | Unknown route or scoped target | | 409 | conflict | Stale edit, conflict, or frozen record | | 429 | rate_limited / request_quota | Finite rate or external allowance exhausted; Retry-After supplied | | 503 | unavailable | Dependency or admission unavailable; fails closed | | 500 | internal_error | Sanitized unexpected failure | An unsupported method returns 405 with Allow. Successful bodyless deletes return 204. Auth uses its generated sanitized credential errors. Do not infer authorization from an HTTP array or a successful related page. Canonical page: [https://docs.nqd.app/v1/guides/errors](https://docs.nqd.app/v1/guides/errors) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD API limits and retries Understand request allowances, plan limits, and when a retry is safe. API requests use Core's finite external allowance and rate groups. No caller header can choose the dashboard channel, unlimited allowance, role, or plan. Credentials and current scope are resolved before the operation's guarded admission and transaction. Rate and request-allowance denials return 429 with Retry-After. Financial record and invitation seat limits return 403 plan_limit. Those outcomes are distinct from current permission denial. Nested client directories consume admission for the parent guard and directory. Batch mutations retain the named Core operation's existing transaction semantics. No generic Idempotency-Key contract is implemented. A lost response can mean a write committed. Read the source and its effective transaction summary before retrying a financial command. Some payment posts support an existing authored transaction ID and report repeated; that capability does not make every POST safe to retry. Transaction updates and deletes are explicit mutations on the addressed transaction, so retry them only after checking whether the first request committed. Server clients without Origin are supported. Browser API access permits only configured HTTPS origins and the declared headers; it does not allow credentialed cookies. CORS is not permission. Preflight executes no business operation. Every actual request authenticates normally. Live traffic, provider cutover, deployment, durable generic retry deduplication, and new scheduling or storage services are outside the current API contract. Canonical page: [https://docs.nqd.app/v1/guides/limits](https://docs.nqd.app/v1/guides/limits) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD API integrations and webhooks Manage API keys, signed webhooks, delivery attempts, and activity logs from Dash or the workspace-scoped API. The same resources are available in Dash under **Settings → Integrations** and through the API. ## Create an API key Sign in to Dash, open **Settings → Integrations → API keys**, choose **Create API key**, enter a name, and select the scopes the integration needs. The secret is shown once. Copy it into your secret manager immediately; NQD stores only the verifier and never displays the secret again. Revoke the key from the same page when it is no longer needed. The API equivalent uses a normal bearer credential and an explicit workspace header: ```bash curl "$API/v1/integrations/api-keys" \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" \ -H "Content-Type: application/json" \ --json '{ "name": "warehouse sync", "scopes": ["invoices.list"] }' ``` The request contains one API key definition. The response places metadata and a one-time `secret` in `data`. Use the secret as the bearer credential. Lists expose scopes, last-use time, and revocation state, never the secret. `DELETE /v1/integrations/api-keys/{apiKeyId}` revokes a key. ## Webhooks Create a webhook from **Settings → Integrations → Webhooks** or `POST /v1/webhooks` with a name, HTTPS destination, and event names. A new webhook starts as `pending_verification`. Call `POST /v1/webhooks/{webhookId}/verify` after confirming the destination. An active webhook signs each delivery with the one-time `signingSecret` returned at creation. Verify `webhook-id`, `webhook-timestamp`, and `webhook-signature` before processing a payload. Use the test action to validate a receiver without authoring a financial record. REST returns the signing secret once when a webhook is created or rotated, with caching disabled. CLI and MCP redact it by default. Pass `--reveal-secrets` to `nqd webhooks create` or `nqd webhooks rotate`, or set `revealSecrets: true` on the matching MCP tool, to receive that one-time value. Save it directly in your receiver's secret manager. Webhook lists, logs, errors, and local workspace state never expose it. Rotation preserves a verified webhook's active or paused state. `overlapSeconds` accepts 60 through 86,400 seconds and defaults to 86,400. For example, `nqd webhooks WEBHOOK_ID rotate --overlap-seconds 3600 --reveal-secrets` gives an hour to update the receiver. During overlap, `webhook-signature` contains space-separated `v1,` values from the new and previous secrets. After expiry, sends and retries use only the new secret. A second rotation during an active overlap returns a conflict; wait for expiry before rotating again. A pending destination stays pending, and changing the destination clears the overlap and requires verification. NQD stores both secrets encrypted and never returns the previous secret. Delivery states are `pending`, `delivering`, `unknown`, `succeeded`, and `failed`. An `unknown` result means that NQD cannot confirm the receiver's outcome. Show it as **Unconfirmed**. Each attempt records its status, category, HTTP status, latency, and a response excerpt limited to 512 bytes. Unknown attempts become manually retryable after five minutes; fresh unknown attempts cannot be retried before then, and succeeded deliveries cannot be retried. Retry one with `POST /v1/webhooks/{webhookId}/deliveries/{logId}/retry`; pause or resume a webhook while investigating failures. The event body is a CloudEvents-shaped JSON object. It contains the event ID, action, workspace ID, record ID, actor ID, operation ID, and occurrence time. NQD signs the exact raw body. Verify `webhook-id`, `webhook-timestamp`, and `webhook-signature` before processing the event. Deduplicate on `webhook-id`, because a receiver can see more than one delivery attempt. The signed body has this shape. `actorId` and `operationId` may be `null` when the committed mutation has no authenticated actor or operation identifier. ```json { "specversion": "1.0", "id": "log_01...", "source": "/workspaces/workspace_01...", "type": "invoices.upsert", "subject": "invoice_01...", "time": "2026-10-10T12:00:00.000Z", "datacontenttype": "application/json", "dataschema": "/schemas/webhooks/invoices.upsert/1.0.0.json", "data": { "workspaceId": "workspace_01...", "recordId": "invoice_01...", "actorId": "profile_01...", "operationId": "invoices.upsert" } } ``` ## Logs `GET /v1/logs` returns immutable workspace activity generated by successfully committed workspace mutations. Filter with `filter[action]=eq.`, use `limit` up to 250, and continue with `page.nextCursor`. Validation failure, permission denial, or a rolled-back transaction creates no activity fact. Log responses contain fixed identity fields, not arbitrary metadata, request bodies, secrets, or raw credentials. Core writes the activity fact and pending delivery in the same database transaction. Delivery starts after commit. A failed delivery never rolls back the domain mutation. The same durable worker runs after commit and on the private five-minute Netlify schedule. It retries network failures, timeouts, HTTP 5xx, and HTTP 408, 425, or 429, with increasing delays and jitter. A valid `Retry-After` is bounded to two hours. Redirects, other HTTP 4xx, unsafe destinations, TLS failures, and invalid configuration stop automatic retries. There are at most eight automatic attempts, including the initial send. Delivery lists expose `nextAttemptAt` and `leaseExpiresAt`; internal lease tokens stay private. Manual retries remain available for eligible pending, failed, or cooled-down unconfirmed deliveries. Test deliveries create a `webhooks.test` activity and delivery row for the selected webhook, without creating an unrelated financial or domain mutation. Webhook signatures are base64 HMAC-SHA256 values over the exact raw body. Pausing a verified webhook keeps matching committed events queued. Resume wakes the bounded worker and replays them in event order; repeated resume does not duplicate queued attempts. Unverified destinations cannot be paused or resumed into service. Changing the destination requires verification again and marks older unresolved deliveries as `stale_generation`, so their events cannot reach the new endpoint. Their attempt history remains available. Editing a name or keeping the same destination preserves verification. A request already in flight to the old destination may finish. All integration routes require a valid bearer credential, the selected `Workspace-Id`, and the caller's workspace settings permission where the operation changes configuration. ## Configure integration retention Retention controls apply to one workspace. Cleanup is disabled by default. Set `enabled` to `true` to allow automatic cleanup. Set either retention window to `null` to keep that record type forever. A configured window accepts an integer from 1 through 3650 days. The REST operations use these paths: | Operation | Request | | ------------------- | ---------------------------------------- | | Read policy | `GET /v1/retention` | | Replace policy | `PUT /v1/retention` | | Preview cleanup | `GET /v1/retention/preview` | | Prune eligible rows | `POST /v1/retention/prune` | All four operations require the selected `Workspace-Id` and the caller's workspace settings permission. `retention.prune` is destructive in the operation catalog and MCP annotations. Update the policy with a complete body: ```bash curl "$API/v1/retention" \ -X PUT \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" \ -H "Content-Type: application/json" \ --json '{ "enabled": true, "logRetentionDays": 90, "deliveryRetentionDays": 30 }' ``` Preview before pruning. The response includes `policyRevision`, candidate counts, protected counts, protected reasons, and the oldest candidate times. Use the returned revision in the prune request: ```bash curl "$API/v1/retention/preview" \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" curl "$API/v1/retention/prune" \ -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Workspace-Id: $WORKSPACE" \ -H "Content-Type: application/json" \ --json '{ "policyRevision": "", "maxRows": 100, "confirm": "prune" }' ``` `maxRows` is optional and accepts an integer from 1 through 1000. The revision and confirmation prevent a prune against a policy that changed after preview. Prune removes eligible terminal delivery rows before unreferenced logs. It keeps pending, delivering, and unknown deliveries, failed deliveries with a current scheduled retry, paused webhook backlog, in-flight work, and logs that any delivery still references. Financial records are outside this policy and are never removed. Automatic maintenance is bounded and visits enabled workspaces fairly. It does not delete rows for disabled policies or null windows. Expired previous webhook secrets use an independent cleanup pass, so secret cleanup does not depend on retention being enabled. The same operations are available as native CLI commands: ```sh nqd integrations retention get nqd integrations retention update --body '{"enabled":true,"logRetentionDays":90,"deliveryRetentionDays":30}' nqd integrations retention preview nqd integrations retention prune --body '{"policyRevision":"","maxRows":100,"confirm":"prune"}' ``` MCP exposes the operation IDs `retention.get`, `retention.update`, `retention.preview`, and `retention.prune`. Set `workspaceId` in each call. Pass the update or prune fields in the matching tool input. The prune tool requires the same `policyRevision` and `confirm` values as REST, with optional `maxRows`. Canonical page: [https://docs.nqd.app/v1/guides/integrations](https://docs.nqd.app/v1/guides/integrations) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD CLI installation and commands Install nqd, authenticate with OAuth or an API key, and manage NQD resources with native commands. The CLI site publishes install scripts, native downloads, checksums, and machine-readable help. The installer and native downloads remain on the CLI origin. The Docs site links to them but does not proxy binary files. Open the CLI landing page to choose macOS, Linux, or Windows. Use `?platform=macos`, `?platform=linux`, or `?platform=windows` to override platform detection. Use `?lang=en` or `?lang=ar` to choose the page language. ## Install Use the install command published by the CLI site for your platform. The Unix installer is: ```sh curl -fsSL https://cli.nqd.app/install.sh | sh ``` The Windows PowerShell installer is: ```powershell irm https://cli.nqd.app/install.ps1 | iex ``` The installers verify `SHA256SUMS` before placing `nqd` on your `PATH`. The release archives target macOS ARM64 and x64, Linux ARM64 and x64, and Windows ARM64 and x64. Set `NQD_CLI_VERSION` to select a release. Set `NQD_CLI_RELEASE_BASE` to use another HTTPS release host or a local development host. The Unix installer uses `$NQD_INSTALL_DIR` or `$HOME/.local/bin`. It persists the path for zsh and bash, and prints a `PATH` command for other shells. The PowerShell installer uses `$NQD_INSTALL_DIR` or `$env:LOCALAPPDATA\NQD`, then updates the user and current-process `Path` values. ## Sign in with OAuth ```bash nqd login ``` The command opens the Auth origin, uses S256 PKCE and a state value, receives the callback on a loopback listener, and stores the token in the native credential manager. The token response includes the consented `workspace_id`. It checks that the issuer and API resource match the configured origins. Use `nqd logout` to revoke the stored grant and remove the local credential. ## Use an API key ```bash NQD_API_KEY=nqd_live_... nqd invoices --limit 25 ``` API keys are suitable for automation. Store them in the runtime secret manager. Do not commit them or place them in a URL. ## Use native resource commands Native commands follow the resource hierarchy. `nqd invoices` lists invoices with the API defaults. `nqd invoices ` retrieves one invoice, and `nqd invoices get ` is an explicit equivalent. Every published REST operation has a native command generated from the same API contract, so you do not need an operation ID for normal work. ```sh nqd invoices nqd invoices get invoice_01J... nqd invoices create --body @invoice.json nqd invoices update invoice_01J... --body @invoice-update.json nqd invoices delete invoice_01J... ``` Use the same form for expenses, income, payouts, assets, clients, vendors, contacts, projects, currencies, entries, modifiers, tags, units, bank accounts, webhooks, API keys, and other published resources. Use `nqd help ` for a resource, or `nqd help ` for an action. The generated help lists only commands and fields that the API provides. Nested resources keep the parent ID in the command path: ```sh nqd invoices invoice_01J... transactions nqd invoices invoice_01J... transactions create --id transaction_01J... --signed-amount 250.00 --currency-id currency_01J... nqd invoices templates ``` ## Manage party contacts Clients and vendors expose contacts as child resources. List contacts without an operation name. Add or remove a contact with its positional ID. ```sh nqd clients CLIENT_ID contacts nqd clients CLIENT_ID contacts add CONTACT_ID nqd clients CLIENT_ID contacts remove CONTACT_ID nqd vendors VENDOR_ID contacts nqd vendors VENDOR_ID contacts add CONTACT_ID nqd vendors VENDOR_ID contacts remove CONTACT_ID ``` ## Manage applied entries and modifiers Invoices, expenses, income, assets, payouts, and their recurring templates use the same child workflow. The source ID comes first, followed by `entries` or `modifiers`. ```sh nqd invoices INVOICE_ID entries nqd invoices INVOICE_ID entries add CATALOG_ENTRY_ID --if-match UPDATED_AT --name Hosting --quantity 2 --price-per-unit 100 nqd invoices INVOICE_ID entries update APPLIED_ENTRY_ID --if-match UPDATED_AT --quantity 3 nqd invoices INVOICE_ID entries remove APPLIED_ENTRY_ID --if-match UPDATED_AT nqd invoices INVOICE_ID entries reorder APPLIED_ENTRY_ID OTHER_APPLIED_ENTRY_ID --if-match UPDATED_AT nqd invoices INVOICE_ID modifiers nqd invoices INVOICE_ID modifiers add CATALOG_MODIFIER_ID --if-match UPDATED_AT --name ServiceFee --kind percentage --stage price --effect increase --value 15 nqd invoices INVOICE_ID modifiers update APPLIED_MODIFIER_ID --if-match UPDATED_AT --value 20 nqd invoices INVOICE_ID modifiers remove APPLIED_MODIFIER_ID --if-match UPDATED_AT nqd invoices INVOICE_ID modifiers reorder APPLIED_MODIFIER_ID OTHER_APPLIED_MODIFIER_ID --if-match UPDATED_AT ``` Use the same child paths with `expenses`, `income`, `assets`, `payouts`, `invoices templates`, `expenses templates`, and `payouts templates`. Replace the source ID with the record or recurring-template ID. The positional catalog ID is optional. When supplied, it links the new applied record to a catalog definition. The catalog ID and applied record ID remain separate. For recurring templates, place the template collection and template ID before the child resource, such as `nqd invoices templates TEMPLATE_ID entries` or `nqd expenses templates TEMPLATE_ID modifiers`. Pass the source response's current `updatedAt` value to `--if-match`. Stale mutations fail instead of overwriting a newer edit. Entry prices are authored net prices and exclude VAT. Applied modifier `value` uses percentage points: `15` means 15%, while fixed modifiers use the amount in the source currency. Generic catalog modifiers use the stage allowed for that source, such as `price` in the example. For invoices, tax-stage applications use the configured workspace tax modifier; use its catalog ID (for example `TAX_MODIFIER_ID`). Other sources validate modifier stages according to their source rules. Catalog changes do not rewrite saved applied facts, and child edits do not replace recorded payments. Reports use readable names: ```sh nqd reports income-statement --start 2026-01-01 --end 2026-12-31 nqd reports balance-sheet --start 2026-01-01 --end 2026-12-31 ``` Use `--limit`, `--search`, `--order`, `--cursor`, and resource-specific filter flags for list commands. Use API order syntax such as `--order createdAt.desc`. Use a resource ID filter such as `--filter-vendor-id eq.vendor_01J...` when the endpoint exposes it. Body fields use kebab-case flags. The CLI converts them to API field names and validates their types from the API contract. Use `nqd help ` to see the accepted flags and any short aliases. Use `help` as a command word when you want command details: ```sh nqd help invoices create nqd invoices create help ``` Common short flags include `-n` for `--name`, `-d` for `--description`, `-l` for `--limit`, `-s` for `--search`, `-o` for `--order`, `-c` for `--cursor`, `-w` for `--workspace`, `-j` for `--json`, `-b` for `--body`, `-q` for `--query`, and `-t` for `--type`. Use command help for the flags supported by each operation. `-h` and `--help` remain available as option-style help aliases. Use `--body ''` for a complete request body. Use `--body @request.json` to read JSON from a file. Use `--entries ''` only when the operation exposes an entries field. Do not combine `--body` with individual body-field flags. Invoice creation requires `currencyId`, `entries`, and `modifiers`; each invoice entry requires `id`, `name`, `description`, `quantity`, `unit`, and `pricePerUnit`. Recurring template creation requires its complete contract payload, so use `--body @template.json` rather than `--name` alone. When replacing a full invoice modifiers array, preserve each returned `appliedId` for an existing applied modifier, including repeated applications of the same catalog modifier. `appliedId` is the saved child snapshot ID; `catalogModifierId` identifies the catalog definition. Child modifier commands use `APPLIED_MODIFIER_ID` for the saved child. Use `--json` for scripts. Workspace lists preserve the API envelope and add `selectedWorkspaceId` plus a `selected` flag on each record. ## Select a workspace once ```sh nqd workspaces nqd workspaces use workspace_01J... nqd workspaces current ``` The selection is saved under `~/.nqd`, or under the directory named by an absolute `NQD_HOME` value. Later workspace-scoped commands use that selection. The list marks the current workspace. The use command validates access before saving. Pass `--workspace ` for a one-command override. `NQD_WORKSPACE_ID` remains available for automation. The per-call flag takes precedence over the environment variable and the saved selection. The selection is stored separately for each API origin. OAuth tokens stay in the operating system credential manager. The CLI never writes tokens into `~/.nqd`. The CLI exposes the published REST operations through native resource commands. Use `help` at the root, resource, or action level to discover the commands and fields available in the current contract. ## One-time webhook signing secrets CLI responses redact one-time signing secrets by default. Pass `--reveal-secrets` only with webhook creation or rotation when you need the new `signingSecret` in inline output. The option is rejected for other operations, and NQD never stores webhook secrets in workspace files. Canonical page: [https://docs.nqd.app/v1/guides/cli](https://docs.nqd.app/v1/guides/cli) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- # NQD MCP setup and resource operations Use NQD's Streamable HTTP MCP server with resource-bound OAuth or API-key credentials. The MCP server exposes the generated NQD operation catalog through JSON-RPC. It calls Core in process and uses the same input schemas, workspace checks, scopes, rate limits, logs, and webhook behavior as the API. It does not proxy tool calls through the REST API. ## Discover the server Use the deployed MCP origin as the protected resource. The server publishes authorization metadata through the configured Auth origin. Production clients must use HTTPS. ```text GET /.well-known/oauth-protected-resource POST / JSON-RPC initialize, tools/list, and tools/call GET / 405 with `Allow: POST` ``` ## Authenticate Send an API key or an OAuth access token: ```http Authorization: Bearer nqd_oauth_... ``` OAuth tokens must target the exact MCP resource origin. A browser session token or an access token issued for the API resource does not authenticate to MCP. Core checks the grant, membership, expiry, and operation scopes before every tool call. ## Call a tool Tool names are canonical operation IDs. Query tools accept the shared query object. Batch tools accept their declared `items` array. ```json { "jsonrpc": "2.0", "id": "invoices-list", "method": "tools/call", "params": { "name": "invoices.list", "arguments": {"query": {"limit": 25}} } } ``` Read the tool annotations before repeating a call. A lost network response does not prove that a write failed. Reconcile the resource and transaction state before sending a new financial write. Query tools return structured content using Core's `{ data, page }` shape. Batch results use `{ items }` when the operation returns an array. ## One-time webhook signing secrets MCP redacts sensitive response fields by default. Webhook creation and rotation advertise an optional transport-only `revealSecrets` boolean. Set it to `true` when you need the one-time `signingSecret`; NQD strips this control before Core input validation and reveals only that allowlisted field. Other secret fields remain redacted, and lists never return signing secrets. Canonical page: [https://docs.nqd.app/v1/guides/mcp](https://docs.nqd.app/v1/guides/mcp) Machine-readable index: [https://docs.nqd.app/llms.txt](https://docs.nqd.app/llms.txt) --- ## Reference resources # NQD API reference: api-keys Canonical page: [https://docs.nqd.app/v1/reference/api-keys](https://docs.nqd.app/v1/reference/api-keys) This resource exposes 3 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/api-keys [Read the endpoint guide](https://docs.nqd.app/v1/reference/api-keys/list) List API keys ## POST /v1/api-keys [Read the endpoint guide](https://docs.nqd.app/v1/reference/api-keys/create) Create API keys ## DELETE /v1/api-keys/{apiKeyId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/api-keys/delete) Revoke API key --- # NQD API reference: assets Canonical page: [https://docs.nqd.app/v1/reference/assets](https://docs.nqd.app/v1/reference/assets) This resource exposes 17 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/assets [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/list) List assets ## GET /v1/assets/{assetId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/retrieve) Retrieve asset ## POST /v1/assets [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/create) Create assets ## PUT /v1/assets/{assetId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/upsert) Upsert asset ## PUT /v1/assets [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/bulk-upsert) Upsert assets in a batch ## GET /v1/assets/{assetId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/entries/list) List applied entries for an asset ## POST /v1/assets/{assetId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/entries/create) Add applied entry to an asset ## PATCH /v1/assets/{assetId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/entries/update) Partially update applied entry on an asset ## DELETE /v1/assets/{assetId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/entries/delete) Remove applied entry from an asset ## PUT /v1/assets/{assetId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/entries/reorder/upsert) Reorder applied entries for an asset ## GET /v1/assets/{assetId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/modifiers/list) List applied modifiers for an asset ## POST /v1/assets/{assetId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/modifiers/create) Add applied modifier to an asset ## PATCH /v1/assets/{assetId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/modifiers/update) Partially update applied modifier on an asset ## DELETE /v1/assets/{assetId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/modifiers/delete) Remove applied modifier from an asset ## PUT /v1/assets/{assetId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/modifiers/reorder/upsert) Reorder applied modifiers for an asset ## GET /v1/assets/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/transactions/list) List transactions ## POST /v1/assets/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/assets/transactions/create) Record a payment --- # NQD API reference: authentication Canonical page: [https://docs.nqd.app/v1/reference/authentication](https://docs.nqd.app/v1/reference/authentication) This resource exposes 2 operations. Each endpoint has its own request, response, and code examples. ## POST /v1/email/challenges [Read the endpoint guide](https://docs.nqd.app/v1/reference/authentication/email/challenge) Request an email sign-in challenge ## POST /v1/email/verifications [Read the endpoint guide](https://docs.nqd.app/v1/reference/authentication/email/verify) Complete email sign-in and issue a bearer credential --- # NQD API reference: bank-accounts Canonical page: [https://docs.nqd.app/v1/reference/bank-accounts](https://docs.nqd.app/v1/reference/bank-accounts) This resource exposes 6 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/bank-accounts [Read the endpoint guide](https://docs.nqd.app/v1/reference/bank-accounts/list) List bank accounts ## POST /v1/bank-accounts [Read the endpoint guide](https://docs.nqd.app/v1/reference/bank-accounts/create) Create bank accounts ## PUT /v1/bank-accounts/{bankAccountId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/bank-accounts/upsert) Upsert bank account ## DELETE /v1/bank-accounts/{bankAccountId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/bank-accounts/delete) Archive bank account ## PUT /v1/bank-accounts [Read the endpoint guide](https://docs.nqd.app/v1/reference/bank-accounts/bulk-upsert) Upsert bank accounts in a batch ## PUT /v1/bank-accounts/defaults [Read the endpoint guide](https://docs.nqd.app/v1/reference/bank-accounts/defaults/set) Update bank accounts defaults --- # NQD API reference: checkouts Canonical page: [https://docs.nqd.app/v1/reference/checkouts](https://docs.nqd.app/v1/reference/checkouts) This resource exposes 1 operations. Each endpoint has its own request, response, and code examples. ## POST /v1/checkouts [Read the endpoint guide](https://docs.nqd.app/v1/reference/checkouts/create) Create a billing checkout session --- # NQD API reference: clients Canonical page: [https://docs.nqd.app/v1/reference/clients](https://docs.nqd.app/v1/reference/clients) This resource exposes 9 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/clients [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/list) List clients ## GET /v1/clients/{clientId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/retrieve) Retrieve client ## POST /v1/clients [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/create) Create clients ## PUT /v1/clients/{clientId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/upsert) Upsert client ## DELETE /v1/clients/{clientId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/delete) Delete client ## PUT /v1/clients [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/bulk-upsert) Upsert clients in a batch ## GET /v1/clients/{clientId}/contacts [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/contacts/list) List client contacts ## POST /v1/clients/{clientId}/contacts/{contactId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/contacts/create) Add a contact to a client ## DELETE /v1/clients/{clientId}/contacts/{contactId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/clients/contacts/delete) Remove a contact from a client --- # NQD API reference: contacts Canonical page: [https://docs.nqd.app/v1/reference/contacts](https://docs.nqd.app/v1/reference/contacts) This resource exposes 6 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/contacts [Read the endpoint guide](https://docs.nqd.app/v1/reference/contacts/list) List contacts ## GET /v1/contacts/{contactId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/contacts/retrieve) Retrieve contact ## POST /v1/contacts [Read the endpoint guide](https://docs.nqd.app/v1/reference/contacts/create) Create contacts ## PUT /v1/contacts/{contactId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/contacts/upsert) Upsert contact ## DELETE /v1/contacts/{contactId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/contacts/delete) Delete contact ## PUT /v1/contacts [Read the endpoint guide](https://docs.nqd.app/v1/reference/contacts/bulk-upsert) Upsert contacts in a batch --- # NQD API reference: currencies Canonical page: [https://docs.nqd.app/v1/reference/currencies](https://docs.nqd.app/v1/reference/currencies) This resource exposes 7 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/currencies [Read the endpoint guide](https://docs.nqd.app/v1/reference/currencies/list) List currencies ## GET /v1/currencies/{currencyId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/currencies/retrieve) Retrieve currency ## POST /v1/currencies [Read the endpoint guide](https://docs.nqd.app/v1/reference/currencies/create) Create currencies ## PUT /v1/currencies/{currencyId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/currencies/upsert) Upsert currency ## DELETE /v1/currencies/{currencyId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/currencies/delete) Archive currency ## PUT /v1/currencies [Read the endpoint guide](https://docs.nqd.app/v1/reference/currencies/bulk-upsert) Upsert currencies in a batch ## PUT /v1/currencies/default [Read the endpoint guide](https://docs.nqd.app/v1/reference/currencies/set-default) Set the default currency --- # NQD API reference: entries Canonical page: [https://docs.nqd.app/v1/reference/entries](https://docs.nqd.app/v1/reference/entries) This resource exposes 6 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/entries/list) List catalog entries ## GET /v1/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/entries/retrieve) Retrieve catalog entry ## POST /v1/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/entries/create) Create catalog entries ## PUT /v1/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/entries/upsert) Upsert catalog entry ## DELETE /v1/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/entries/delete) Archive catalog entry ## PUT /v1/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/entries/bulk-upsert) Upsert catalog entries in a batch --- # NQD API reference: expenses Canonical page: [https://docs.nqd.app/v1/reference/expenses](https://docs.nqd.app/v1/reference/expenses) This resource exposes 18 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/expenses [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/list) List expenses ## GET /v1/expenses/{expenseId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/retrieve) Retrieve expense ## POST /v1/expenses [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/create) Create expenses ## PUT /v1/expenses/{expenseId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/upsert) Upsert expense ## DELETE /v1/expenses/{expenseId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/delete) Delete expense ## PUT /v1/expenses [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/bulk-upsert) Upsert expenses in a batch ## GET /v1/expenses/{expenseId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/entries/list) List applied entries for an expense ## POST /v1/expenses/{expenseId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/entries/create) Add applied entry to an expense ## PATCH /v1/expenses/{expenseId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/entries/update) Partially update applied entry on an expense ## DELETE /v1/expenses/{expenseId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/entries/delete) Remove applied entry from an expense ## PUT /v1/expenses/{expenseId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/entries/reorder/upsert) Reorder applied entries for an expense ## GET /v1/expenses/{expenseId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/modifiers/list) List applied modifiers for an expense ## POST /v1/expenses/{expenseId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/modifiers/create) Add applied modifier to an expense ## PATCH /v1/expenses/{expenseId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/modifiers/update) Partially update applied modifier on an expense ## DELETE /v1/expenses/{expenseId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/modifiers/delete) Remove applied modifier from an expense ## PUT /v1/expenses/{expenseId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/modifiers/reorder/upsert) Reorder applied modifiers for an expense ## GET /v1/expenses/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/transactions/list) List transactions ## POST /v1/expenses/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/transactions/create) Record a payment --- # NQD API reference: expense-templates Canonical page: [https://docs.nqd.app/v1/reference/expenses/templates](https://docs.nqd.app/v1/reference/expenses/templates) This resource exposes 15 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/expenses/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/list) List expense templates ## POST /v1/expenses/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/create) Create expense templates ## PUT /v1/expenses/templates/{templateId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/upsert) Upsert expense template ## DELETE /v1/expenses/templates/{templateId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/delete) Delete expense template ## PUT /v1/expenses/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/bulk-upsert) Upsert expense templates in a batch ## GET /v1/expenses/templates/{templateId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/entries/list) List applied entries for an expense template ## POST /v1/expenses/templates/{templateId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/entries/create) Add applied entry to an expense template ## PATCH /v1/expenses/templates/{templateId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/entries/update) Partially update applied entry on an expense template ## DELETE /v1/expenses/templates/{templateId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/entries/delete) Remove applied entry from an expense template ## PUT /v1/expenses/templates/{templateId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/entries/reorder/upsert) Reorder applied entries for an expense template ## GET /v1/expenses/templates/{templateId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/list) List applied modifiers for an expense template ## POST /v1/expenses/templates/{templateId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/create) Add applied modifier to an expense template ## PATCH /v1/expenses/templates/{templateId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/update) Partially update applied modifier on an expense template ## DELETE /v1/expenses/templates/{templateId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/delete) Remove applied modifier from an expense template ## PUT /v1/expenses/templates/{templateId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/reorder/upsert) Reorder applied modifiers for an expense template --- # NQD API reference: income Canonical page: [https://docs.nqd.app/v1/reference/income](https://docs.nqd.app/v1/reference/income) This resource exposes 18 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/income [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/list) List income records ## GET /v1/income/{incomeId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/retrieve) Retrieve income record ## POST /v1/income [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/create) Create income records ## PUT /v1/income/{incomeId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/upsert) Upsert income record ## DELETE /v1/income/{incomeId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/delete) Delete income record ## PUT /v1/income [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/bulk-upsert) Upsert income records in a batch ## GET /v1/income/{incomeId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/entries/list) List applied entries for an income record ## POST /v1/income/{incomeId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/entries/create) Add applied entry to an income record ## PATCH /v1/income/{incomeId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/entries/update) Partially update applied entry on an income record ## DELETE /v1/income/{incomeId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/entries/delete) Remove applied entry from an income record ## PUT /v1/income/{incomeId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/entries/reorder/upsert) Reorder applied entries for an income record ## GET /v1/income/{incomeId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/modifiers/list) List applied modifiers for an income record ## POST /v1/income/{incomeId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/modifiers/create) Add applied modifier to an income record ## PATCH /v1/income/{incomeId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/modifiers/update) Partially update applied modifier on an income record ## DELETE /v1/income/{incomeId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/modifiers/delete) Remove applied modifier from an income record ## PUT /v1/income/{incomeId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/modifiers/reorder/upsert) Reorder applied modifiers for an income record ## GET /v1/income/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/transactions/list) List transactions ## POST /v1/income/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/income/transactions/create) Record a payment --- # NQD API reference: invitations Canonical page: [https://docs.nqd.app/v1/reference/invitations](https://docs.nqd.app/v1/reference/invitations) This resource exposes 5 operations. Each endpoint has its own request, response, and code examples. ## POST /v1/invitations [Read the endpoint guide](https://docs.nqd.app/v1/reference/invitations/create) Create workspace participant ## DELETE /v1/invitations/{inviteId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invitations/delete) Revoke workspace participant ## POST /v1/invitations/{inviteId}/redeliveries [Read the endpoint guide](https://docs.nqd.app/v1/reference/invitations/redeliveries/create) Resend a workspace invitation ## POST /v1/invitations/acceptances [Read the endpoint guide](https://docs.nqd.app/v1/reference/invitations/acceptances/create) Accept pending workspace invitations ## GET /v1/invitations/pending [Read the endpoint guide](https://docs.nqd.app/v1/reference/invitations/pending) List pending workspace invitations --- # NQD API reference: invoices Canonical page: [https://docs.nqd.app/v1/reference/invoices](https://docs.nqd.app/v1/reference/invoices) This resource exposes 18 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/invoices [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/list) List invoices ## GET /v1/invoices/{invoiceId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/retrieve) Retrieve invoice ## POST /v1/invoices [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/create) Create invoices ## PUT /v1/invoices/{invoiceId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/upsert) Upsert invoice ## DELETE /v1/invoices/{invoiceId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/delete) Delete invoice ## PUT /v1/invoices [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/bulk-upsert) Upsert invoices in a batch ## GET /v1/invoices/{invoiceId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/entries/list) List applied entries for an invoice ## POST /v1/invoices/{invoiceId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/entries/create) Add applied entry to an invoice ## PATCH /v1/invoices/{invoiceId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/entries/update) Partially update applied entry on an invoice ## DELETE /v1/invoices/{invoiceId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/entries/delete) Remove applied entry from an invoice ## PUT /v1/invoices/{invoiceId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/entries/reorder/upsert) Reorder applied entries for an invoice ## GET /v1/invoices/{invoiceId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/modifiers/list) List applied modifiers for an invoice ## POST /v1/invoices/{invoiceId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/modifiers/create) Add applied modifier to an invoice ## PATCH /v1/invoices/{invoiceId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/modifiers/update) Partially update applied modifier on an invoice ## DELETE /v1/invoices/{invoiceId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/modifiers/delete) Remove applied modifier from an invoice ## PUT /v1/invoices/{invoiceId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/modifiers/reorder/upsert) Reorder applied modifiers for an invoice ## GET /v1/invoices/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/transactions/list) List transactions ## POST /v1/invoices/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/transactions/create) Record a payment --- # NQD API reference: invoice-templates Canonical page: [https://docs.nqd.app/v1/reference/invoices/templates](https://docs.nqd.app/v1/reference/invoices/templates) This resource exposes 15 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/invoices/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/list) List invoice templates ## POST /v1/invoices/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/create) Create invoice templates ## PUT /v1/invoices/templates/{templateId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/upsert) Upsert invoice template ## DELETE /v1/invoices/templates/{templateId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/delete) Delete invoice template ## PUT /v1/invoices/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/bulk-upsert) Upsert invoice templates in a batch ## GET /v1/invoices/templates/{templateId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/entries/list) List applied entries for an invoice template ## POST /v1/invoices/templates/{templateId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/entries/create) Add applied entry to an invoice template ## PATCH /v1/invoices/templates/{templateId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/entries/update) Partially update applied entry on an invoice template ## DELETE /v1/invoices/templates/{templateId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/entries/delete) Remove applied entry from an invoice template ## PUT /v1/invoices/templates/{templateId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/entries/reorder/upsert) Reorder applied entries for an invoice template ## GET /v1/invoices/templates/{templateId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/list) List applied modifiers for an invoice template ## POST /v1/invoices/templates/{templateId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/create) Add applied modifier to an invoice template ## PATCH /v1/invoices/templates/{templateId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/update) Partially update applied modifier on an invoice template ## DELETE /v1/invoices/templates/{templateId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/delete) Remove applied modifier from an invoice template ## PUT /v1/invoices/templates/{templateId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/reorder/upsert) Reorder applied modifiers for an invoice template --- # NQD API reference: logs Canonical page: [https://docs.nqd.app/v1/reference/logs](https://docs.nqd.app/v1/reference/logs) This resource exposes 1 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/logs [Read the endpoint guide](https://docs.nqd.app/v1/reference/logs/list) List integration logs --- # NQD API reference: modifiers Canonical page: [https://docs.nqd.app/v1/reference/modifiers](https://docs.nqd.app/v1/reference/modifiers) This resource exposes 7 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/modifiers/list) List modifiers ## GET /v1/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/modifiers/retrieve) Retrieve modifier ## POST /v1/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/modifiers/create) Create modifiers ## PUT /v1/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/modifiers/upsert) Upsert modifier ## DELETE /v1/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/modifiers/delete) Archive modifier ## PUT /v1/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/modifiers/bulk-upsert) Upsert modifiers in a batch ## PUT /v1/modifiers/tax [Read the endpoint guide](https://docs.nqd.app/v1/reference/modifiers/set-tax) Set the workspace tax modifier --- # NQD API reference: participants Canonical page: [https://docs.nqd.app/v1/reference/participants](https://docs.nqd.app/v1/reference/participants) This resource exposes 3 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/participants [Read the endpoint guide](https://docs.nqd.app/v1/reference/participants/list) List workspace participants ## DELETE /v1/participants/{profileId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/participants/delete) Delete workspace participant ## PUT /v1/participants/{profileId}/role [Read the endpoint guide](https://docs.nqd.app/v1/reference/participants/role/upsert) Update a workspace participant role --- # NQD API reference: payouts Canonical page: [https://docs.nqd.app/v1/reference/payouts](https://docs.nqd.app/v1/reference/payouts) This resource exposes 18 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/payouts [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/list) List payouts ## GET /v1/payouts/{payoutId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/retrieve) Retrieve payout ## POST /v1/payouts [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/create) Create payouts ## PUT /v1/payouts/{payoutId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/upsert) Upsert payout ## DELETE /v1/payouts/{payoutId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/delete) Delete payout ## PUT /v1/payouts [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/bulk-upsert) Upsert payouts in a batch ## GET /v1/payouts/{payoutId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/entries/list) List applied entries for a payout ## POST /v1/payouts/{payoutId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/entries/create) Add applied entry to a payout ## PATCH /v1/payouts/{payoutId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/entries/update) Partially update applied entry on a payout ## DELETE /v1/payouts/{payoutId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/entries/delete) Remove applied entry from a payout ## PUT /v1/payouts/{payoutId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/entries/reorder/upsert) Reorder applied entries for a payout ## GET /v1/payouts/{payoutId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/modifiers/list) List applied modifiers for a payout ## POST /v1/payouts/{payoutId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/modifiers/create) Add applied modifier to a payout ## PATCH /v1/payouts/{payoutId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/modifiers/update) Partially update applied modifier on a payout ## DELETE /v1/payouts/{payoutId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/modifiers/delete) Remove applied modifier from a payout ## PUT /v1/payouts/{payoutId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/modifiers/reorder/upsert) Reorder applied modifiers for a payout ## GET /v1/payouts/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/transactions/list) List transactions ## POST /v1/payouts/{sourceId}/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/transactions/create) Record a payment --- # NQD API reference: payout-templates Canonical page: [https://docs.nqd.app/v1/reference/payouts/templates](https://docs.nqd.app/v1/reference/payouts/templates) This resource exposes 15 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/payouts/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/list) List payout templates ## POST /v1/payouts/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/create) Create payout templates ## PUT /v1/payouts/templates/{templateId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/upsert) Upsert payout template ## DELETE /v1/payouts/templates/{templateId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/delete) Delete payout template ## PUT /v1/payouts/templates [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/bulk-upsert) Upsert payout templates in a batch ## GET /v1/payouts/templates/{templateId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/entries/list) List applied entries for a payout template ## POST /v1/payouts/templates/{templateId}/entries [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/entries/create) Add applied entry to a payout template ## PATCH /v1/payouts/templates/{templateId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/entries/update) Partially update applied entry on a payout template ## DELETE /v1/payouts/templates/{templateId}/entries/{entryId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/entries/delete) Remove applied entry from a payout template ## PUT /v1/payouts/templates/{templateId}/entries/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/entries/reorder/upsert) Reorder applied entries for a payout template ## GET /v1/payouts/templates/{templateId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/list) List applied modifiers for a payout template ## POST /v1/payouts/templates/{templateId}/modifiers [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/create) Add applied modifier to a payout template ## PATCH /v1/payouts/templates/{templateId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/update) Partially update applied modifier on a payout template ## DELETE /v1/payouts/templates/{templateId}/modifiers/{modifierId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/delete) Remove applied modifier from a payout template ## PUT /v1/payouts/templates/{templateId}/modifiers/reorder [Read the endpoint guide](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/reorder/upsert) Reorder applied modifiers for a payout template --- # NQD API reference: plans Canonical page: [https://docs.nqd.app/v1/reference/plans](https://docs.nqd.app/v1/reference/plans) This resource exposes 1 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/plans [Read the endpoint guide](https://docs.nqd.app/v1/reference/plans/list) List available billing plans --- # NQD API reference: preferences Canonical page: [https://docs.nqd.app/v1/reference/preferences](https://docs.nqd.app/v1/reference/preferences) This resource exposes 1 operations. Each endpoint has its own request, response, and code examples. ## PUT /v1/preferences [Read the endpoint guide](https://docs.nqd.app/v1/reference/preferences/upsert) Save workspace preferences --- # NQD API reference: profile Canonical page: [https://docs.nqd.app/v1/reference/profile](https://docs.nqd.app/v1/reference/profile) This resource exposes 4 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/profile [Read the endpoint guide](https://docs.nqd.app/v1/reference/profile/retrieve) Read profile settings ## POST /v1/profile [Read the endpoint guide](https://docs.nqd.app/v1/reference/profile/create) Create the initial profile ## PUT /v1/profile [Read the endpoint guide](https://docs.nqd.app/v1/reference/profile/upsert) Update profile settings ## POST /v1/profile/avatar-uploads [Read the endpoint guide](https://docs.nqd.app/v1/reference/profile/avatar-uploads/create) Create a profile avatar upload --- # NQD API reference: profile-preferences Canonical page: [https://docs.nqd.app/v1/reference/profile/preferences](https://docs.nqd.app/v1/reference/profile/preferences) This resource exposes 2 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/profile/preferences [Read the endpoint guide](https://docs.nqd.app/v1/reference/profile/preferences/list) Read profile preferences ## PUT /v1/profile/preferences [Read the endpoint guide](https://docs.nqd.app/v1/reference/profile/preferences/upsert) Save profile preferences --- # NQD API reference: projects Canonical page: [https://docs.nqd.app/v1/reference/projects](https://docs.nqd.app/v1/reference/projects) This resource exposes 6 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/projects [Read the endpoint guide](https://docs.nqd.app/v1/reference/projects/list) List projects ## GET /v1/projects/{projectId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/projects/retrieve) Retrieve project ## POST /v1/projects [Read the endpoint guide](https://docs.nqd.app/v1/reference/projects/create) Create projects ## PUT /v1/projects/{projectId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/projects/upsert) Upsert project ## DELETE /v1/projects/{projectId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/projects/delete) Delete project ## PUT /v1/projects [Read the endpoint guide](https://docs.nqd.app/v1/reference/projects/bulk-upsert) Upsert projects in a batch --- # NQD API reference: reports Canonical page: [https://docs.nqd.app/v1/reference/reports](https://docs.nqd.app/v1/reference/reports) This resource exposes 14 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/reports/balance-sheet [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/balance-sheet) Read the workspace balance sheet ## GET /v1/reports/cash-flow [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/cash-flow) Read workspace cash flow ## GET /v1/reports/cashbook [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/cashbook) Read the workspace cashbook ## GET /v1/reports/center [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/center) Read the workspace financial center report ## GET /v1/reports/income-statement [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/income-statement) Read the workspace income statement ## GET /v1/reports/movements [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/movements) List workspace financial movements ## GET /v1/reports/overview [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/overview) Read the workspace financial overview report ## GET /v1/reports/payables [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/payables) Read workspace payables aging ## GET /v1/reports/profit-loss [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/profit-loss) Read the workspace profit and loss statement ## GET /v1/reports/receivables [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/receivables) Read workspace receivables aging ## GET /v1/reports/statements [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/statements) Read workspace financial statements ## GET /v1/reports/summary [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/summary) Read the workspace financial summary report ## GET /v1/reports/tax-control [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/tax-control) Read workspace tax control ## GET /v1/reports/trial-balance [Read the endpoint guide](https://docs.nqd.app/v1/reference/reports/trial-balance) Read the workspace trial balance --- # NQD API reference: retention Canonical page: [https://docs.nqd.app/v1/reference/retention](https://docs.nqd.app/v1/reference/retention) This resource exposes 4 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/retention [Read the endpoint guide](https://docs.nqd.app/v1/reference/retention/retrieve) Get integration retention ## PUT /v1/retention [Read the endpoint guide](https://docs.nqd.app/v1/reference/retention/upsert) Update integration retention ## GET /v1/retention/preview [Read the endpoint guide](https://docs.nqd.app/v1/reference/retention/preview/retrieve) Preview integration retention ## POST /v1/retention/prune [Read the endpoint guide](https://docs.nqd.app/v1/reference/retention/prune/create) Prune integration retention --- # NQD API reference: settings Canonical page: [https://docs.nqd.app/v1/reference/settings](https://docs.nqd.app/v1/reference/settings) This resource exposes 3 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/settings [Read the endpoint guide](https://docs.nqd.app/v1/reference/settings/retrieve) Read workspace settings ## PUT /v1/settings [Read the endpoint guide](https://docs.nqd.app/v1/reference/settings/upsert) Update workspace settings ## POST /v1/settings/avatar-uploads [Read the endpoint guide](https://docs.nqd.app/v1/reference/settings/avatar-uploads/create) Create a workspace avatar upload --- # NQD API reference: fiscal-year Canonical page: [https://docs.nqd.app/v1/reference/settings/fiscal-year](https://docs.nqd.app/v1/reference/settings/fiscal-year) This resource exposes 1 operations. Each endpoint has its own request, response, and code examples. ## PUT /v1/settings/fiscal-year [Read the endpoint guide](https://docs.nqd.app/v1/reference/settings/fiscal-year/upsert) Update the workspace fiscal year --- # NQD API reference: payables Canonical page: [https://docs.nqd.app/v1/reference/settings/payables](https://docs.nqd.app/v1/reference/settings/payables) This resource exposes 2 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/settings/payables [Read the endpoint guide](https://docs.nqd.app/v1/reference/settings/payables/list) Read payable settings ## PUT /v1/settings/payables [Read the endpoint guide](https://docs.nqd.app/v1/reference/settings/payables/upsert) Save payable settings --- # NQD API reference: tags Canonical page: [https://docs.nqd.app/v1/reference/tags](https://docs.nqd.app/v1/reference/tags) This resource exposes 6 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/tags [Read the endpoint guide](https://docs.nqd.app/v1/reference/tags/list) List tags ## GET /v1/tags/{tagId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/tags/retrieve) Retrieve tag ## POST /v1/tags [Read the endpoint guide](https://docs.nqd.app/v1/reference/tags/create) Create tags ## PUT /v1/tags/{tagId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/tags/upsert) Upsert tag ## DELETE /v1/tags/{tagId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/tags/delete) Delete tag ## PUT /v1/tags [Read the endpoint guide](https://docs.nqd.app/v1/reference/tags/bulk-upsert) Upsert tags in a batch --- # NQD API reference: transactions Canonical page: [https://docs.nqd.app/v1/reference/transactions](https://docs.nqd.app/v1/reference/transactions) This resource exposes 3 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/transactions [Read the endpoint guide](https://docs.nqd.app/v1/reference/transactions/list) List transactions ## DELETE /v1/transactions/{transactionId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/transactions/delete) Delete a transaction ## PATCH /v1/transactions/{transactionId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/transactions/update) Update a transaction --- # NQD API reference: units Canonical page: [https://docs.nqd.app/v1/reference/units](https://docs.nqd.app/v1/reference/units) This resource exposes 6 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/units [Read the endpoint guide](https://docs.nqd.app/v1/reference/units/list) List units ## GET /v1/units/{code} [Read the endpoint guide](https://docs.nqd.app/v1/reference/units/retrieve) Retrieve unit ## POST /v1/units [Read the endpoint guide](https://docs.nqd.app/v1/reference/units/create) Create units ## PUT /v1/units/{code} [Read the endpoint guide](https://docs.nqd.app/v1/reference/units/upsert) Upsert unit ## DELETE /v1/units/{code} [Read the endpoint guide](https://docs.nqd.app/v1/reference/units/delete) Archive unit ## PUT /v1/units [Read the endpoint guide](https://docs.nqd.app/v1/reference/units/bulk-upsert) Upsert units in a batch --- # NQD API reference: usage Canonical page: [https://docs.nqd.app/v1/reference/usage](https://docs.nqd.app/v1/reference/usage) This resource exposes 1 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/usage [Read the endpoint guide](https://docs.nqd.app/v1/reference/usage/retrieve) Read current billing usage --- # NQD API reference: vendors Canonical page: [https://docs.nqd.app/v1/reference/vendors](https://docs.nqd.app/v1/reference/vendors) This resource exposes 9 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/vendors [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/list) List vendors ## GET /v1/vendors/{vendorId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/retrieve) Retrieve vendor ## POST /v1/vendors [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/create) Create vendors ## PUT /v1/vendors/{vendorId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/upsert) Upsert vendor ## DELETE /v1/vendors/{vendorId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/delete) Delete vendor ## PUT /v1/vendors [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/bulk-upsert) Upsert vendors in a batch ## GET /v1/vendors/{vendorId}/contacts [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/contacts/list) List vendor contacts ## POST /v1/vendors/{vendorId}/contacts/{contactId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/contacts/create) Add a contact to a vendor ## DELETE /v1/vendors/{vendorId}/contacts/{contactId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/vendors/contacts/delete) Remove a contact from a vendor --- # NQD API reference: webhooks Canonical page: [https://docs.nqd.app/v1/reference/webhooks](https://docs.nqd.app/v1/reference/webhooks) This resource exposes 11 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/webhooks [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/list) List webhooks ## POST /v1/webhooks [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/create) Create webhooks ## PUT /v1/webhooks/{webhookId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/upsert) Update webhooks ## DELETE /v1/webhooks/{webhookId} [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/delete) Delete webhook ## GET /v1/webhooks/{webhookId}/deliveries [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/deliveries/list) List webhook deliveries ## POST /v1/webhooks/{webhookId}/deliveries/{logId}/retry [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/deliveries/retry) Retry a failed webhook delivery ## POST /v1/webhooks/{webhookId}/pause [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/pause) Pause webhook deliveries ## POST /v1/webhooks/{webhookId}/resume [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/resume) Resume webhook deliveries ## POST /v1/webhooks/{webhookId}/rotate [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/rotate) Rotate webhook signing credentials ## POST /v1/webhooks/{webhookId}/test [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/test) Send a test webhook delivery ## POST /v1/webhooks/{webhookId}/verify [Read the endpoint guide](https://docs.nqd.app/v1/reference/webhooks/verify) Verify webhook --- # NQD API reference: workspaces Canonical page: [https://docs.nqd.app/v1/reference/workspaces](https://docs.nqd.app/v1/reference/workspaces) This resource exposes 2 operations. Each endpoint has its own request, response, and code examples. ## GET /v1/workspaces [Read the endpoint guide](https://docs.nqd.app/v1/reference/workspaces/list) List workspaces available to the current identity ## POST /v1/workspaces [Read the endpoint guide](https://docs.nqd.app/v1/reference/workspaces/create) Create a workspace --- # List API keys **GET** `/v1/api-keys` Retrieve matching API keys. - Canonical URL: [https://docs.nqd.app/v1/reference/api-keys/list](https://docs.nqd.app/v1/reference/api-keys/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter api-keys by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter api-keys by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[lastUsedAt]` | `string` | No | No | Filter api-keys by lastUsedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[revokedAt]` | `string` | No | No | Filter api-keys by revokedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter api-keys by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2B"` | | `data[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data[].scopes` | `string[]` | Yes | No | Permissions granted to the API key. | `["read"]` | | `data[].lastUsedAt` | `string` | Yes | Yes | ISO 8601 timestamp of the credential's most recent use. | `"2026-01-15T12:00:00.000Z"` | | `data[].revokedAt` | `string` | Yes | Yes | ISO 8601 timestamp for revoked. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P2B", "name": "NQD record", "scopes": [ "read" ], "lastUsedAt": "2026-01-15T12:00:00.000Z", "revokedAt": null, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/api-keys" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/api-keys", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/api-keys failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - The secret is returned only when the key is created. Store it securely; later list responses expose metadata only. --- # Create API keys **POST** `/v1/api-keys` Create API keys from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/api-keys/create](https://docs.nqd.app/v1/reference/api-keys/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `scopes` | `string[]` | No | Yes | Permissions granted to the API key. (at least 1 items, at most 100 items) | `["read"]` | ```json [ { "name": "NQD record" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].key` | `object` | Yes | No | key for this api key. | — | | `data[].key.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2B"` | | `data[].key.name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data[].key.scopes` | `string[]` | Yes | No | Permissions granted to the API key. | `["read"]` | | `data[].key.lastUsedAt` | `string` | Yes | Yes | ISO 8601 timestamp of the credential's most recent use. | `"2026-01-15T12:00:00.000Z"` | | `data[].key.revokedAt` | `string` | Yes | Yes | ISO 8601 timestamp for revoked. | `null` | | `data[].key.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].secret` | `string` | Yes | No | One-time secret returned when the credential is created. | `"whsec_01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ```json { "data": [ { "key": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P2B", "name": "NQD record", "scopes": [ "read" ], "lastUsedAt": "2026-01-15T12:00:00.000Z", "revokedAt": null, "createdAt": "2026-01-15T12:00:00.000Z" }, "secret": "whsec_01JQ2T5Y5Q3R8W9N6M4K2H7P1A" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/api-keys" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/api-keys", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/api-keys failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - The secret is returned only when the key is created. Store it securely; later list responses expose metadata only. --- # Revoke API key **DELETE** `/v1/api-keys/{apiKeyId}` Revoke API key. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/api-keys/delete](https://docs.nqd.app/v1/reference/api-keys/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `apiKeyId` | `string` | Yes | No | An opaque api_key resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2B"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/api-keys/01JQ2T5Y5Q3R8W9N6M4K2H7P2B" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/api-keys/01JQ2T5Y5Q3R8W9N6M4K2H7P2B", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/api-keys/01JQ2T5Y5Q3R8W9N6M4K2H7P2B failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - The secret is returned only when the key is created. Store it securely; later list responses expose metadata only. --- # List assets **GET** `/v1/assets` Retrieve matching assets. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/list](https://docs.nqd.app/v1/reference/assets/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter assets by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter assets by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter assets by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter assets by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[createdBy]` | `string` | No | No | Filter assets by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedBy]` | `string` | No | No | Filter assets by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[createdAt]` | `string` | No | No | Filter assets by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter assets by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[currencyId]` | `string` | No | No | Filter assets by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter assets by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `locale` | `en \| ar` | No | No | Operation context value for locale. (one of en, ar) | `"en"` | | `asOf` | `string` | No | No | Operation context value for asOf. | `"2026-01-15T12:00:00Z"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Laptop"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"15-inch business laptop"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Laptop"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "name": "Laptop", "description": "15-inch business laptop", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/assets failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Retrieve asset **GET** `/v1/assets/{assetId}` Return the addressed asset. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/retrieve](https://docs.nqd.app/v1/reference/assets/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `locale` | `string` | No | No | Optional locale filter or query option. (Allowed values: "en", "ar") | `"en"` | | `asOf` | `string` | No | No | Optional as of filter or query option. | `"2026-01-15T12:00:00.000Z"` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Laptop"` | | `data.description` | `string` | Yes | No | Optional human-readable description of the record. | `"15-inch business laptop"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "name": "Laptop", "description": "15-inch business laptop", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Create assets **POST** `/v1/assets` Create a non-cash Asset holding from authored entries and modifiers. A separate cash Transaction may record its acquisition. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/create](https://docs.nqd.app/v1/reference/assets/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Laptop"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Laptop"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | ```json [ { "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Laptop"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"15-inch business laptop"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Laptop"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "name": "Laptop", "description": "15-inch business laptop", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/assets failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Upsert asset **PUT** `/v1/assets/{assetId}` Upsert a non-cash Asset holding, preserving authored entries, modifiers, exact decimal values, and selected currency. Acquisition cash belongs in a separate Transaction. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/upsert](https://docs.nqd.app/v1/reference/assets/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Laptop"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Laptop"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | ```json { "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Laptop"` | | `data.description` | `string` | Yes | No | Optional human-readable description of the record. | `"15-inch business laptop"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "name": "Laptop", "description": "15-inch business laptop", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Upsert assets in a batch **PUT** `/v1/assets` Upsert assets atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/bulk-upsert](https://docs.nqd.app/v1/reference/assets/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Laptop"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Laptop"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Laptop"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"15-inch business laptop"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Laptop"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "name": "Laptop", "description": "15-inch business laptop", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Laptop", "description": "15-inch business laptop", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "tags": [ "equipment" ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Laptop", "description": "15-inch business laptop", "quantity": "1.00", "unit": "item", "pricePerUnit": "3000.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/assets failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List applied entries for an asset **GET** `/v1/assets/{assetId}/entries` Return the complete applied collection snapshot for an asset. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/entries/list](https://docs.nqd.app/v1/reference/assets/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Add applied entry to an asset **POST** `/v1/assets/{assetId}/entries` Add applied entry to an asset and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/entries/create](https://docs.nqd.app/v1/reference/assets/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Laptop", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Laptop", "description": "15-inch business laptop", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Laptop", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Laptop", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Partially update applied entry on an asset **PATCH** `/v1/assets/{assetId}/entries/{entryId}` Partially update applied entry on an asset and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/entries/update](https://docs.nqd.app/v1/reference/assets/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Laptop" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Laptop", "description": "15-inch business laptop", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Laptop" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Laptop" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied entry from an asset **DELETE** `/v1/assets/{assetId}/entries/{entryId}` Remove applied entry from an asset and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/entries/delete](https://docs.nqd.app/v1/reference/assets/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Reorder applied entries for an asset **PUT** `/v1/assets/{assetId}/entries/reorder` Replace the complete order of applied entries for an asset and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/entries/reorder/upsert](https://docs.nqd.app/v1/reference/assets/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # List applied modifiers for an asset **GET** `/v1/assets/{assetId}/modifiers` Return the complete applied collection snapshot for an asset. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/modifiers/list](https://docs.nqd.app/v1/reference/assets/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "1.00", "pricePerUnit": "3000.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Add applied modifier to an asset **POST** `/v1/assets/{assetId}/modifiers` Add applied modifier to an asset and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/modifiers/create](https://docs.nqd.app/v1/reference/assets/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `kind` | `string` | No | Yes | kind for this asset. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this asset. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this asset. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "1.00", "pricePerUnit": "3000.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Partially update applied modifier on an asset **PATCH** `/v1/assets/{assetId}/modifiers/{modifierId}` Partially update applied modifier on an asset and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/modifiers/update](https://docs.nqd.app/v1/reference/assets/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `kind` | `string` | No | Yes | kind for this asset. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this asset. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this asset. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "1.00", "pricePerUnit": "3000.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied modifier from an asset **DELETE** `/v1/assets/{assetId}/modifiers/{modifierId}` Remove applied modifier from an asset and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/modifiers/delete](https://docs.nqd.app/v1/reference/assets/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # Reorder applied modifiers for an asset **PUT** `/v1/assets/{assetId}/modifiers/reorder` Replace the complete order of applied modifiers for an asset and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/assets/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `assetId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1N"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1N" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Laptop"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"15-inch business laptop"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3000.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Laptop", "description": "15-inch business laptop", "unitCode": "item", "quantity": "1.00", "pricePerUnit": "3000.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1N" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1N" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Asset is a non-cash holding. Its acquisition may have a separate cash Transaction, so the holding and the cash event remain distinct. --- # List transactions **GET** `/v1/assets/{sourceId}/transactions` Retrieve matching transactions. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/transactions/list](https://docs.nqd.app/v1/reference/assets/transactions/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter assets by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[amount]` | `string` | No | No | Filter assets by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[direction]` | `string` | No | No | Filter assets by direction. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.inbound"` | | `filter[createdAt]` | `string` | No | No | Filter assets by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[bankAccountId]` | `string` | No | No | Filter assets by bankAccountId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[originalId]` | `string` | No | No | Filter assets by originalId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceId]` | `string` | No | No | Filter assets by sourceId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceType]` | `string` | No | No | Filter assets by sourceType. Use operator.value syntax. (eq, neq, in operators) | `"eq.invoice"` | | `filter[currencyCode]` | `string` | No | No | Filter assets by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,source"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,amount.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `data[].source` | `object` | Yes | Yes | source for this asset. | — | | `data[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | | `data[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].direction` | `string` | Yes | No | direction for this asset. (Allowed values: "inbound", "outbound") | `"inbound"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].accountLabel` | `string` | No | Yes | account label for this asset. | `"Consulting services"` | | `data[].originalId` | `string` | Yes | Yes | ID of the related original. | `"Consulting services"` | | `data[].context` | `object` | Yes | No | context for this asset. | — | | `data[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1N", "type": "invoice" }, "amount": "100.00", "direction": "inbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "bankAccountId": null, "originalId": "Consulting services", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # Record a payment **POST** `/v1/assets/{sourceId}/transactions` Record a payment against the source using its currency and the selected or default bank account. - Canonical URL: [https://docs.nqd.app/v1/reference/assets/transactions/create](https://docs.nqd.app/v1/reference/assets/transactions/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque asset resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1N"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this asset. | `true` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": true } } ``` ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this asset. | `false` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": false } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/assets/01JQ2T5Y5Q3R8W9N6M4K2H7P1N/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. - The payment uses the source currency and the selected or configured workspace bank account; validate conversion when currencies differ. --- # Request an email sign-in challenge **POST** `/v1/email/challenges` Start passwordless sign-in by sending a one-time challenge to the requested email address. - Canonical URL: [https://docs.nqd.app/v1/reference/authentication/email/challenge](https://docs.nqd.app/v1/reference/authentication/email/challenge) - Scope: anonymous ## Request headers No additional request headers are documented for this operation. ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `email` | `string` | Yes | No | Email address associated with the identity. (Maximum length: 254 characters.) | `"owner@example.com"` | ```json { "email": "owner@example.com" } ``` ## Responses ### 200 — AuthEmailChallengeReply Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.accepted` | `boolean` | Yes | No | accepted for this authentication. | `true` | ```json { "data": { "accepted": true } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"invalid_request"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"cors_forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request origin is not allowed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "cors_forbidden", "message": "The request origin is not allowed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_AUTH_URL:-http://auth.nqd.localhost:1335}/v1/email/challenges" \ -H "Content-Type: application/json" \ --data '{ "email": "owner@example.com" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/email/challenges", env.NQD_AUTH_URL ?? "http://auth.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ "email": "owner@example.com" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/email/challenges failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Complete email sign-in and issue a bearer credential **POST** `/v1/email/verifications` Verify the one-time email challenge and return the bearer credential used by authenticated requests. - Canonical URL: [https://docs.nqd.app/v1/reference/authentication/email/verify](https://docs.nqd.app/v1/reference/authentication/email/verify) - Scope: anonymous ## Request headers No additional request headers are documented for this operation. ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `email` | `string` | Yes | No | Email address associated with the identity. (Maximum length: 254 characters.) | `"owner@example.com"` | | `code` | `string` | Yes | No | Stable code used to identify this catalog value or machine-readable result. | `"123456"` | ```json { "email": "owner@example.com", "code": "123456" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `access_token` | `string` | Yes | No | Bearer credential returned by authentication. (Minimum length: 1 character.) | `"example_access_token"` | | `token_type` | `string` | Yes | No | Bearer token type returned by authentication. (Allowed values: "bearer") | `"bearer"` | | `expires_at` | `number` | Yes | No | Unix timestamp when the credential expires. | `1768482000` | ```json { "access_token": "example_access_token", "token_type": "bearer", "expires_at": 1768482000 } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"invalid_request"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"cors_forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request origin is not allowed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "cors_forbidden", "message": "The request origin is not allowed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "unsupported_media_type", "body_too_large", "body_timeout", "invalid_request") | `"expected_type"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_AUTH_URL:-http://auth.nqd.localhost:1335}/v1/email/verifications" \ -H "Content-Type: application/json" \ --data '{ "email": "owner@example.com", "code": "123456" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/email/verifications", env.NQD_AUTH_URL ?? "http://auth.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ "email": "owner@example.com", "code": "123456" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/email/verifications failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List bank accounts **GET** `/v1/bank-accounts` Retrieve matching bank accounts. - Canonical URL: [https://docs.nqd.app/v1/reference/bank-accounts/list](https://docs.nqd.app/v1/reference/bank-accounts/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter bank-accounts by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[label]` | `string` | No | No | Filter bank-accounts by label. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[bankName]` | `string` | No | No | Filter bank-accounts by bankName. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[accountName]` | `string` | No | No | Filter bank-accounts by accountName. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[accountNumber]` | `string` | No | No | Filter bank-accounts by accountNumber. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[iban]` | `string` | No | No | Filter bank-accounts by iban. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[currencyId]` | `string` | No | No | Filter bank-accounts by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[archivedAt]` | `string` | No | No | Filter bank-accounts by archivedAt. Use operator.value syntax. (eq, neq, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter bank-accounts by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter bank-accounts by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,label"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,label.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `data[].label` | `string` | Yes | Yes | Human-readable label for the value. | `"Operating account"` | | `data[].bankName` | `string` | Yes | Yes | bank name for this bank account. | `"NQD Bank"` | | `data[].accountName` | `string` | Yes | Yes | account name for this bank account. | `"Operating account"` | | `data[].accountNumber` | `string` | Yes | Yes | account number for this bank account. | `"Consulting services"` | | `data[].iban` | `string` | Yes | Yes | iban for this bank account. | `"SA0380000000608010167519"` | | `data[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. | `null` | | `data[].archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G", "label": "Operating account", "bankName": "NQD Bank", "accountName": "Operating account", "accountNumber": "Consulting services", "iban": "SA0380000000608010167519", "currencyId": null, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/bank-accounts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/bank-accounts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/bank-accounts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create bank accounts **POST** `/v1/bank-accounts` Create bank accounts from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/bank-accounts/create](https://docs.nqd.app/v1/reference/bank-accounts/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `label` | `string` | No | Yes | Human-readable label for the value. (Maximum length: 2048 characters.) | `"Operating account"` | | `bankName` | `string` | No | Yes | bank name for this bank account. (Maximum length: 2048 characters.) | `"NQD Bank"` | | `accountName` | `string` | No | Yes | account name for this bank account. (Maximum length: 2048 characters.) | `"Operating account"` | | `accountNumber` | `string` | No | Yes | account number for this bank account. (Maximum length: 2048 characters.) | `"Consulting services"` | | `iban` | `string` | No | Yes | iban for this bank account. (Maximum length: 2048 characters.) | `"SA0380000000608010167519"` | | `currencyId` | `string` | No | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | ```json [ {} ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `data[].label` | `string` | Yes | Yes | Human-readable label for the value. | `"Operating account"` | | `data[].bankName` | `string` | Yes | Yes | bank name for this bank account. | `"NQD Bank"` | | `data[].accountName` | `string` | Yes | Yes | account name for this bank account. | `"Operating account"` | | `data[].accountNumber` | `string` | Yes | Yes | account number for this bank account. | `"Consulting services"` | | `data[].iban` | `string` | Yes | Yes | iban for this bank account. | `"SA0380000000608010167519"` | | `data[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. | `null` | | `data[].archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G", "label": "Operating account", "bankName": "NQD Bank", "accountName": "Operating account", "accountNumber": "Consulting services", "iban": "SA0380000000608010167519", "currencyId": null, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/bank-accounts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ {} ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/bank-accounts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ {} ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/bank-accounts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert bank account **PUT** `/v1/bank-accounts/{bankAccountId}` Create or update the addressed bank account. - Canonical URL: [https://docs.nqd.app/v1/reference/bank-accounts/upsert](https://docs.nqd.app/v1/reference/bank-accounts/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | Yes | No | An opaque workspace_bank_account resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `label` | `string` | No | Yes | Human-readable label for the value. (Maximum length: 2048 characters.) | `"Operating account"` | | `bankName` | `string` | No | Yes | bank name for this bank account. (Maximum length: 2048 characters.) | `"NQD Bank"` | | `accountName` | `string` | No | Yes | account name for this bank account. (Maximum length: 2048 characters.) | `"Operating account"` | | `accountNumber` | `string` | No | Yes | account number for this bank account. (Maximum length: 2048 characters.) | `"Consulting services"` | | `iban` | `string` | No | Yes | iban for this bank account. (Maximum length: 2048 characters.) | `"SA0380000000608010167519"` | | `currencyId` | `string` | No | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `data.label` | `string` | Yes | Yes | Human-readable label for the value. | `"Operating account"` | | `data.bankName` | `string` | Yes | Yes | bank name for this bank account. | `"NQD Bank"` | | `data.accountName` | `string` | Yes | Yes | account name for this bank account. | `"Operating account"` | | `data.accountNumber` | `string` | Yes | Yes | account number for this bank account. | `"Consulting services"` | | `data.iban` | `string` | Yes | Yes | iban for this bank account. | `"SA0380000000608010167519"` | | `data.currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. | `null` | | `data.archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G", "label": "Operating account", "bankName": "NQD Bank", "accountName": "Operating account", "accountNumber": "Consulting services", "iban": "SA0380000000608010167519", "currencyId": null, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/bank-accounts/01JQ2T5Y5Q3R8W9N6M4K2H7P1G" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/bank-accounts/01JQ2T5Y5Q3R8W9N6M4K2H7P1G", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/bank-accounts/01JQ2T5Y5Q3R8W9N6M4K2H7P1G failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Archive bank account **DELETE** `/v1/bank-accounts/{bankAccountId}` Archive bank account. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/bank-accounts/delete](https://docs.nqd.app/v1/reference/bank-accounts/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | Yes | No | An opaque workspace_bank_account resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/bank-accounts/01JQ2T5Y5Q3R8W9N6M4K2H7P1G" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/bank-accounts/01JQ2T5Y5Q3R8W9N6M4K2H7P1G", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/bank-accounts/01JQ2T5Y5Q3R8W9N6M4K2H7P1G failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert bank accounts in a batch **PUT** `/v1/bank-accounts` Upsert bank accounts atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/bank-accounts/bulk-upsert](https://docs.nqd.app/v1/reference/bank-accounts/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `label` | `string` | No | Yes | Human-readable label for the value. (Maximum length: 2048 characters.) | `"Operating account"` | | `bankName` | `string` | No | Yes | bank name for this bank account. (Maximum length: 2048 characters.) | `"NQD Bank"` | | `accountName` | `string` | No | Yes | account name for this bank account. (Maximum length: 2048 characters.) | `"Operating account"` | | `accountNumber` | `string` | No | Yes | account number for this bank account. (Maximum length: 2048 characters.) | `"Consulting services"` | | `iban` | `string` | No | Yes | iban for this bank account. (Maximum length: 2048 characters.) | `"SA0380000000608010167519"` | | `currencyId` | `string` | No | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | ```json [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `data[].label` | `string` | Yes | Yes | Human-readable label for the value. | `"Operating account"` | | `data[].bankName` | `string` | Yes | Yes | bank name for this bank account. | `"NQD Bank"` | | `data[].accountName` | `string` | Yes | Yes | account name for this bank account. | `"Operating account"` | | `data[].accountNumber` | `string` | Yes | Yes | account number for this bank account. | `"Consulting services"` | | `data[].iban` | `string` | Yes | Yes | iban for this bank account. | `"SA0380000000608010167519"` | | `data[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. | `null` | | `data[].archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G", "label": "Operating account", "bankName": "NQD Bank", "accountName": "Operating account", "accountNumber": "Consulting services", "iban": "SA0380000000608010167519", "currencyId": null, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/bank-accounts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/bank-accounts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/bank-accounts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Update bank accounts defaults **PUT** `/v1/bank-accounts/defaults` Update bank accounts defaults. - Canonical URL: [https://docs.nqd.app/v1/reference/bank-accounts/defaults/set](https://docs.nqd.app/v1/reference/bank-accounts/defaults/set) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `defaultInvoiceBankAccountId` | `string` | No | Yes | ID of the related default invoice bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `defaultIncomeBankAccountId` | `string` | No | Yes | ID of the related default income bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `defaultAssetBankAccountId` | `string` | No | Yes | ID of the related default asset bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `defaultExpenseBankAccountId` | `string` | No | Yes | ID of the related default expense bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `defaultPayoutBankAccountId` | `string` | No | Yes | ID of the related default payout bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `defaultExpenseRecurringBankAccountId` | `string` | No | Yes | ID of the related default expense recurring bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `defaultBankAccountPurpose` | `string` | No | Yes | default bank account purpose for this bank account. (Allowed values: "invoice", "income", "asset", "expense", "payout", "expenseRecurring") | `"invoice"` | ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.slug` | `string` | Yes | No | slug for this bank account. | `"acme-workspace"` | | `data.officialName` | `string` | Yes | Yes | official name for this bank account. | `"Consulting services"` | | `data.tradeName` | `string` | Yes | Yes | trade name for this bank account. | `"Consulting services"` | | `data.registrationNumber` | `string` | Yes | Yes | registration number for this bank account. | `"CR-0001234567"` | | `data.taxId` | `string` | Yes | Yes | ID of the related tax. | `"100.00"` | | `data.defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. | `null` | | `data.defaultInvoiceBankAccountId` | `string` | Yes | Yes | ID of the related default invoice bank account. | `null` | | `data.defaultIncomeBankAccountId` | `string` | Yes | Yes | ID of the related default income bank account. | `null` | | `data.defaultAssetBankAccountId` | `string` | Yes | Yes | ID of the related default asset bank account. | `null` | | `data.defaultExpenseBankAccountId` | `string` | Yes | Yes | ID of the related default expense bank account. | `null` | | `data.defaultPayoutBankAccountId` | `string` | Yes | Yes | ID of the related default payout bank account. | `null` | | `data.defaultExpenseRecurringBankAccountId` | `string` | Yes | Yes | ID of the related default expense recurring bank account. | `null` | | `data.email` | `string` | Yes | Yes | Email address associated with the identity. | `"owner@example.com"` | | `data.phone` | `string` | Yes | Yes | phone for this bank account. | `"+966500000000"` | | `data.address` | `string` | Yes | Yes | address for this bank account. | `"King Fahd Road"` | | `data.city` | `string` | Yes | Yes | city for this bank account. | `"Riyadh"` | | `data.state` | `string` | Yes | Yes | Current state of the record or operation. | `"Riyadh"` | | `data.postalCode` | `string` | Yes | Yes | postal code for this bank account. | `"Consulting services"` | | `data.country` | `string` | Yes | Yes | country for this bank account. | `"SA"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this bank account. | `null` | | `data.fiscalYearStartAt` | `string` | Yes | Yes | ISO 8601 timestamp for fiscal year start. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G", "name": "NQD record", "slug": "acme-workspace", "officialName": "Consulting services", "tradeName": "Consulting services", "registrationNumber": "CR-0001234567", "taxId": "100.00", "defaultCurrencyId": null, "defaultInvoiceBankAccountId": null, "defaultIncomeBankAccountId": null, "defaultAssetBankAccountId": null, "defaultExpenseBankAccountId": null, "defaultPayoutBankAccountId": null, "defaultExpenseRecurringBankAccountId": null, "email": "owner@example.com", "phone": "+966500000000", "address": "King Fahd Road", "city": "Riyadh", "state": "Riyadh", "postalCode": "Consulting services", "country": "SA", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "fiscalYearStartAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/bank-accounts/defaults" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/bank-accounts/defaults", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/bank-accounts/defaults failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create a billing checkout session **POST** `/v1/checkouts` Create a billing checkout session. - Canonical URL: [https://docs.nqd.app/v1/reference/checkouts/create](https://docs.nqd.app/v1/reference/checkouts/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `productId` | `string` | Yes | No | ID of the related product. (Allowed values: "pro", "business", "enterprise", "elite") | `"pro"` | | `variantId` | `string` | Yes | No | ID of the related variant. (Allowed values: "monthly", "yearly") | `"monthly"` | | `locale` | `string` | Yes | No | locale for this checkout. (Allowed values: "en", "ar") | `"en"` | | `returnUrl` | `string` | Yes | No | return url for this checkout. (Maximum length: 2048 characters.) | `"https://example.com/hooks/nqd"` | ```json { "productId": "pro", "variantId": "monthly", "locale": "en", "returnUrl": "https://example.com/hooks/nqd" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.url` | `string` | Yes | No | HTTPS destination that receives webhook deliveries. | `"https://example.com/hooks/nqd"` | ```json { "data": { "url": "https://example.com/hooks/nqd" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/checkouts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "productId": "pro", "variantId": "monthly", "locale": "en", "returnUrl": "https://example.com/hooks/nqd" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/checkouts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "productId": "pro", "variantId": "monthly", "locale": "en", "returnUrl": "https://example.com/hooks/nqd" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/checkouts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List clients **GET** `/v1/clients` Retrieve matching clients. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/list](https://docs.nqd.app/v1/reference/clients/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter clients by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter clients by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter clients by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[industry]` | `string` | No | No | Filter clients by industry. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[type]` | `string` | No | No | Filter clients by type. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.company"` | | `filter[tags]` | `string` | No | No | Filter clients by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[createdAt]` | `string` | No | No | Filter clients by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter clients by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[prospectedAt]` | `string` | No | No | Filter clients by prospectedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[convertedAt]` | `string` | No | No | Filter clients by convertedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[inactivatedAt]` | `string` | No | No | Filter clients by inactivatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string[]` | Yes | Yes | website for this client. | `["https://example.com/hooks/nqd"]` | | `data[].industry` | `string[]` | Yes | Yes | industry for this client. | `["Consulting services"]` | | `data[].type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].prospectedAt` | `string` | Yes | No | ISO 8601 timestamp for prospected. | `"2026-01-15T12:00:00.000Z"` | | `data[].convertedAt` | `string` | Yes | Yes | ISO 8601 timestamp for converted. | `"2026-01-15T12:00:00.000Z"` | | `data[].inactivatedAt` | `string` | Yes | Yes | ISO 8601 timestamp for inactivated. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "tags": [ "equipment" ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "prospectedAt": "2026-01-15T12:00:00.000Z", "convertedAt": "2026-01-15T12:00:00.000Z", "inactivatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/clients failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve client **GET** `/v1/clients/{clientId}` Return the addressed client. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/retrieve](https://docs.nqd.app/v1/reference/clients/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | No | An opaque client resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.website` | `string[]` | Yes | Yes | website for this client. | `["https://example.com/hooks/nqd"]` | | `data.industry` | `string[]` | Yes | Yes | industry for this client. | `["Consulting services"]` | | `data.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create clients **POST** `/v1/clients` Create clients from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/create](https://docs.nqd.app/v1/reference/clients/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string[]` | No | Yes | website for this client. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `industry` | `string[]` | No | Yes | industry for this client. (at most 100 items) | `["Consulting services"]` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string[]` | Yes | Yes | website for this client. | `["https://example.com/hooks/nqd"]` | | `data[].industry` | `string[]` | Yes | Yes | industry for this client. | `["Consulting services"]` | | `data[].type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/clients failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert client **PUT** `/v1/clients/{clientId}` Create or update the addressed client. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/upsert](https://docs.nqd.app/v1/reference/clients/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | No | An opaque client resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string[]` | No | Yes | website for this client. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `industry` | `string[]` | No | Yes | industry for this client. (at most 100 items) | `["Consulting services"]` | ```json { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.website` | `string[]` | Yes | Yes | website for this client. | `["https://example.com/hooks/nqd"]` | | `data.industry` | `string[]` | Yes | Yes | industry for this client. | `["Consulting services"]` | | `data.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete client **DELETE** `/v1/clients/{clientId}` Delete client. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/delete](https://docs.nqd.app/v1/reference/clients/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | No | An opaque client resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert clients in a batch **PUT** `/v1/clients` Upsert clients atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/bulk-upsert](https://docs.nqd.app/v1/reference/clients/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string[]` | No | Yes | website for this client. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `industry` | `string[]` | No | Yes | industry for this client. (at most 100 items) | `["Consulting services"]` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string[]` | Yes | Yes | website for this client. | `["https://example.com/hooks/nqd"]` | | `data[].industry` | `string[]` | Yes | Yes | industry for this client. | `["Consulting services"]` | | `data[].type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/clients failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List client contacts **GET** `/v1/clients/{clientId}/contacts` List client contacts. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/contacts/list](https://docs.nqd.app/v1/reference/clients/contacts/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | No | An opaque client resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter clients by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[clientId]` | `string` | No | No | Filter clients by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[vendorId]` | `string` | No | No | Filter clients by vendorId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[name]` | `string` | No | No | Filter clients by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter clients by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[bank]` | `string` | No | No | Filter clients by bank. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[iban]` | `string` | No | No | Filter clients by iban. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter clients by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[createdAt]` | `string` | No | No | Filter clients by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter clients by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,clientId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,clientId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data[].vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data[].phone` | `string[]` | Yes | Yes | phone for this client. | `["+966500000000"]` | | `data[].website` | `string[]` | Yes | Yes | website for this client. | `["https://example.com/hooks/nqd"]` | | `data[].position` | `string[]` | Yes | Yes | position for this client. | `["Consulting services"]` | | `data[].bank` | `string` | Yes | Yes | bank for this client. | `"NQD Bank"` | | `data[].iban` | `string` | Yes | Yes | iban for this client. | `"SA0380000000608010167519"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bank": "NQD Bank", "iban": "SA0380000000608010167519", "tags": [ "equipment" ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Add a contact to a client **POST** `/v1/clients/{clientId}/contacts/{contactId}` Add a contact to a client. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/contacts/create](https://docs.nqd.app/v1/reference/clients/contacts/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | No | An opaque client resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `contactId` | `string` | Yes | No | An opaque contact resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data.vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data.phone` | `string[]` | Yes | Yes | phone for this client. | `["+966500000000"]` | | `data.website` | `string[]` | Yes | Yes | website for this client. | `["https://example.com/hooks/nqd"]` | | `data.position` | `string[]` | Yes | Yes | position for this client. | `["Consulting services"]` | | `data.bankName` | `string` | Yes | Yes | bank name for this client. | `"NQD Bank"` | | `data.iban` | `string` | Yes | Yes | iban for this client. | `"SA0380000000608010167519"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bankName": "NQD Bank", "iban": "SA0380000000608010167519", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Remove a contact from a client **DELETE** `/v1/clients/{clientId}/contacts/{contactId}` Remove a contact from a client. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/clients/contacts/delete](https://docs.nqd.app/v1/reference/clients/contacts/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | No | An opaque client resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `contactId` | `string` | Yes | No | An opaque contact resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/clients/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List contacts **GET** `/v1/contacts` Retrieve matching contacts. - Canonical URL: [https://docs.nqd.app/v1/reference/contacts/list](https://docs.nqd.app/v1/reference/contacts/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter contacts by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[clientId]` | `string` | No | No | Filter contacts by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[vendorId]` | `string` | No | No | Filter contacts by vendorId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[name]` | `string` | No | No | Filter contacts by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter contacts by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[bank]` | `string` | No | No | Filter contacts by bank. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[iban]` | `string` | No | No | Filter contacts by iban. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter contacts by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[createdAt]` | `string` | No | No | Filter contacts by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter contacts by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,clientId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,clientId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data[].clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data[].vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data[].phone` | `string[]` | Yes | Yes | phone for this contact. | `["+966500000000"]` | | `data[].website` | `string[]` | Yes | Yes | website for this contact. | `["https://example.com/hooks/nqd"]` | | `data[].position` | `string[]` | Yes | Yes | position for this contact. | `["Consulting services"]` | | `data[].bank` | `string` | Yes | Yes | bank for this contact. | `"NQD Bank"` | | `data[].iban` | `string` | Yes | Yes | iban for this contact. | `"SA0380000000608010167519"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bank": "NQD Bank", "iban": "SA0380000000608010167519", "tags": [ "equipment" ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/contacts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/contacts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/contacts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve contact **GET** `/v1/contacts/{contactId}` Return the addressed contact. - Canonical URL: [https://docs.nqd.app/v1/reference/contacts/retrieve](https://docs.nqd.app/v1/reference/contacts/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `contactId` | `string` | Yes | No | An opaque contact resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data.clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data.vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data.phone` | `string[]` | Yes | Yes | phone for this contact. | `["+966500000000"]` | | `data.website` | `string[]` | Yes | Yes | website for this contact. | `["https://example.com/hooks/nqd"]` | | `data.position` | `string[]` | Yes | Yes | position for this contact. | `["Consulting services"]` | | `data.bankName` | `string` | Yes | Yes | bank name for this contact. | `"NQD Bank"` | | `data.iban` | `string` | Yes | Yes | iban for this contact. | `"SA0380000000608010167519"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bankName": "NQD Bank", "iban": "SA0380000000608010167519", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create contacts **POST** `/v1/contacts` Create contacts from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/contacts/create](https://docs.nqd.app/v1/reference/contacts/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `clientId` | `string` | No | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `vendorId` | `string` | No | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `email` | `string[]` | No | Yes | Email address associated with the identity. (at most 100 items) | `["owner@example.com"]` | | `phone` | `string[]` | No | Yes | phone for this contact. (at most 100 items) | `["+966500000000"]` | | `website` | `string[]` | No | Yes | website for this contact. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `position` | `string[]` | No | Yes | position for this contact. (at most 100 items) | `["Consulting services"]` | | `bankName` | `string` | No | Yes | bank name for this contact. (Maximum length: 10000 characters.) | `"NQD Bank"` | | `iban` | `string` | No | Yes | iban for this contact. (Maximum length: 10000 characters.) | `"SA0380000000608010167519"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data[].clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data[].vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data[].phone` | `string[]` | Yes | Yes | phone for this contact. | `["+966500000000"]` | | `data[].website` | `string[]` | Yes | Yes | website for this contact. | `["https://example.com/hooks/nqd"]` | | `data[].position` | `string[]` | Yes | Yes | position for this contact. | `["Consulting services"]` | | `data[].bankName` | `string` | Yes | Yes | bank name for this contact. | `"NQD Bank"` | | `data[].iban` | `string` | Yes | Yes | iban for this contact. | `"SA0380000000608010167519"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bankName": "NQD Bank", "iban": "SA0380000000608010167519", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/contacts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/contacts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/contacts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert contact **PUT** `/v1/contacts/{contactId}` Create or update the addressed contact. - Canonical URL: [https://docs.nqd.app/v1/reference/contacts/upsert](https://docs.nqd.app/v1/reference/contacts/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `contactId` | `string` | Yes | No | An opaque contact resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `clientId` | `string` | No | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `vendorId` | `string` | No | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `email` | `string[]` | No | Yes | Email address associated with the identity. (at most 100 items) | `["owner@example.com"]` | | `phone` | `string[]` | No | Yes | phone for this contact. (at most 100 items) | `["+966500000000"]` | | `website` | `string[]` | No | Yes | website for this contact. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `position` | `string[]` | No | Yes | position for this contact. (at most 100 items) | `["Consulting services"]` | | `bankName` | `string` | No | Yes | bank name for this contact. (Maximum length: 10000 characters.) | `"NQD Bank"` | | `iban` | `string` | No | Yes | iban for this contact. (Maximum length: 10000 characters.) | `"SA0380000000608010167519"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | ```json { "name": "NQD record", "description": "Consulting services for January 2026" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data.clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data.vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data.phone` | `string[]` | Yes | Yes | phone for this contact. | `["+966500000000"]` | | `data.website` | `string[]` | Yes | Yes | website for this contact. | `["https://example.com/hooks/nqd"]` | | `data.position` | `string[]` | Yes | Yes | position for this contact. | `["Consulting services"]` | | `data.bankName` | `string` | Yes | Yes | bank name for this contact. | `"NQD Bank"` | | `data.iban` | `string` | Yes | Yes | iban for this contact. | `"SA0380000000608010167519"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bankName": "NQD Bank", "iban": "SA0380000000608010167519", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record", "description": "Consulting services for January 2026" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record", "description": "Consulting services for January 2026" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete contact **DELETE** `/v1/contacts/{contactId}` Delete contact. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/contacts/delete](https://docs.nqd.app/v1/reference/contacts/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `contactId` | `string` | Yes | No | An opaque contact resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert contacts in a batch **PUT** `/v1/contacts` Upsert contacts atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/contacts/bulk-upsert](https://docs.nqd.app/v1/reference/contacts/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `clientId` | `string` | No | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `vendorId` | `string` | No | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `email` | `string[]` | No | Yes | Email address associated with the identity. (at most 100 items) | `["owner@example.com"]` | | `phone` | `string[]` | No | Yes | phone for this contact. (at most 100 items) | `["+966500000000"]` | | `website` | `string[]` | No | Yes | website for this contact. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `position` | `string[]` | No | Yes | position for this contact. (at most 100 items) | `["Consulting services"]` | | `bankName` | `string` | No | Yes | bank name for this contact. (Maximum length: 10000 characters.) | `"NQD Bank"` | | `iban` | `string` | No | Yes | iban for this contact. (Maximum length: 10000 characters.) | `"SA0380000000608010167519"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data[].clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data[].vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data[].phone` | `string[]` | Yes | Yes | phone for this contact. | `["+966500000000"]` | | `data[].website` | `string[]` | Yes | Yes | website for this contact. | `["https://example.com/hooks/nqd"]` | | `data[].position` | `string[]` | Yes | Yes | position for this contact. | `["Consulting services"]` | | `data[].bankName` | `string` | Yes | Yes | bank name for this contact. | `"NQD Bank"` | | `data[].iban` | `string` | Yes | Yes | iban for this contact. | `"SA0380000000608010167519"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bankName": "NQD Bank", "iban": "SA0380000000608010167519", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/contacts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/contacts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/contacts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List currencies **GET** `/v1/currencies` Retrieve matching currencies. - Canonical URL: [https://docs.nqd.app/v1/reference/currencies/list](https://docs.nqd.app/v1/reference/currencies/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter currencies by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter currencies by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter currencies by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[createdAt]` | `string` | No | No | Filter currencies by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter currencies by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[from]` | `string` | No | No | Filter currencies by from. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[to]` | `string` | No | No | Filter currencies by to. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[rate]` | `string` | No | No | Filter currencies by rate. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"US Dollar"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"US Dollar reporting conversion to Saudi Riyal"` | | `data[].conversion` | `object` | Yes | No | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. | `"USD"` | | `data[].conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. | `"SAR"` | | `data[].conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"3.75"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "conversion": { "from": "USD", "to": "SAR", "rate": "3.75" }, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/currencies" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/currencies", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/currencies failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve currency **GET** `/v1/currencies/{currencyId}` Return the addressed currency. - Canonical URL: [https://docs.nqd.app/v1/reference/currencies/retrieve](https://docs.nqd.app/v1/reference/currencies/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `currencyId` | `string` | Yes | No | An opaque currency resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"US Dollar"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"US Dollar reporting conversion to Saudi Riyal"` | | `data.conversion` | `object` | Yes | No | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. | `"USD"` | | `data.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. | `"SAR"` | | `data.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"3.75"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "conversion": { "from": "USD", "to": "SAR", "rate": "3.75" }, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create currencies **POST** `/v1/currencies` Create currencies from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/currencies/create](https://docs.nqd.app/v1/reference/currencies/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"US Dollar"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"US Dollar reporting conversion to Saudi Riyal"` | | `sourceCurrencyCode` | `string` | Yes | No | ISO 4217 code of the source currency. (Maximum length: 32 characters.) | `"USD"` | | `targetCurrencyCode` | `string` | Yes | No | ISO 4217 code of the target currency. (Maximum length: 32 characters.) | `"SAR"` | | `conversionRate` | `string` | Yes | No | Exact decimal rate from the source currency to the target currency. (Maximum length: 128 characters.) | `"3.75"` | ```json [ { "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"US Dollar"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"US Dollar reporting conversion to Saudi Riyal"` | | `data[].conversion` | `object` | Yes | No | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. | `"USD"` | | `data[].conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. | `"SAR"` | | `data[].conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"3.75"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "conversion": { "from": "USD", "to": "SAR", "rate": "3.75" }, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/currencies" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/currencies", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/currencies failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert currency **PUT** `/v1/currencies/{currencyId}` Create or update the addressed currency. - Canonical URL: [https://docs.nqd.app/v1/reference/currencies/upsert](https://docs.nqd.app/v1/reference/currencies/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `currencyId` | `string` | Yes | No | An opaque currency resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"US Dollar"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"US Dollar reporting conversion to Saudi Riyal"` | | `sourceCurrencyCode` | `string` | Yes | No | ISO 4217 code of the source currency. (Maximum length: 32 characters.) | `"USD"` | | `targetCurrencyCode` | `string` | Yes | No | ISO 4217 code of the target currency. (Maximum length: 32 characters.) | `"SAR"` | | `conversionRate` | `string` | Yes | No | Exact decimal rate from the source currency to the target currency. (Maximum length: 128 characters.) | `"3.75"` | ```json { "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"US Dollar"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"US Dollar reporting conversion to Saudi Riyal"` | | `data.conversion` | `object` | Yes | No | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. | `"USD"` | | `data.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. | `"SAR"` | | `data.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"3.75"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "conversion": { "from": "USD", "to": "SAR", "rate": "3.75" }, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Archive currency **DELETE** `/v1/currencies/{currencyId}` Archive currency. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/currencies/delete](https://docs.nqd.app/v1/reference/currencies/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `currencyId` | `string` | Yes | No | An opaque currency resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/currencies/01JQ2T5Y5Q3R8W9N6M4K2H7P1F failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert currencies in a batch **PUT** `/v1/currencies` Upsert currencies atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/currencies/bulk-upsert](https://docs.nqd.app/v1/reference/currencies/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"US Dollar"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"US Dollar reporting conversion to Saudi Riyal"` | | `sourceCurrencyCode` | `string` | Yes | No | ISO 4217 code of the source currency. (Maximum length: 32 characters.) | `"USD"` | | `targetCurrencyCode` | `string` | Yes | No | ISO 4217 code of the target currency. (Maximum length: 32 characters.) | `"SAR"` | | `conversionRate` | `string` | Yes | No | Exact decimal rate from the source currency to the target currency. (Maximum length: 128 characters.) | `"3.75"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | ```json [ { "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"US Dollar"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"US Dollar reporting conversion to Saudi Riyal"` | | `data[].conversion` | `object` | Yes | No | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. | `"USD"` | | `data[].conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. | `"SAR"` | | `data[].conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"3.75"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "conversion": { "from": "USD", "to": "SAR", "rate": "3.75" }, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/currencies" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/currencies", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "US Dollar", "description": "US Dollar reporting conversion to Saudi Riyal", "sourceCurrencyCode": "USD", "targetCurrencyCode": "SAR", "conversionRate": "3.75", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/currencies failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Set the default currency **PUT** `/v1/currencies/default` Set the workspace default currency. - Canonical URL: [https://docs.nqd.app/v1/reference/currencies/set-default](https://docs.nqd.app/v1/reference/currencies/set-default) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | ```json { "defaultCurrencyId": null } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. | `null` | ```json { "data": { "defaultCurrencyId": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | ISO 4217 currency code, such as SAR or USD. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/currencies/default" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "defaultCurrencyId": null }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/currencies/default", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "defaultCurrencyId": null }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/currencies/default failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List catalog entries **GET** `/v1/entries` Retrieve matching catalog entries. - Canonical URL: [https://docs.nqd.app/v1/reference/entries/list](https://docs.nqd.app/v1/reference/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter entries by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[code]` | `string` | No | No | Filter entries by code. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[name]` | `string` | No | No | Filter entries by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter entries by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[unitCode]` | `string` | No | No | Filter entries by unitCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[quantity]` | `string` | No | No | Filter entries by quantity. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[pricePerUnit]` | `string` | No | No | Filter entries by pricePerUnit. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[createdAt]` | `string` | No | No | Filter entries by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter entries by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[currencyId]` | `string` | No | No | Filter entries by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,code"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,code.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].code` | `string` | Yes | Yes | Stable machine-readable error or resource code. | `"Consulting services"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. | `"hour"` | | `data[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "code": "Consulting services", "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "Service fee", "value": "5" } ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve catalog entry **GET** `/v1/entries/{entryId}` Return the addressed catalog entry. - Canonical URL: [https://docs.nqd.app/v1/reference/entries/retrieve](https://docs.nqd.app/v1/reference/entries/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `entryId` | `string` | Yes | No | An opaque entry resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.code` | `string` | Yes | Yes | Stable machine-readable error or resource code. | `"Consulting services"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.unitCode` | `string` | Yes | No | Unit code from the workspace catalog. | `"hour"` | | `data.quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "code": "Consulting services", "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "Service fee", "value": "5" } ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create catalog entries **POST** `/v1/entries` Create catalog entries from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/entries/create](https://docs.nqd.app/v1/reference/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | No | Yes | Stable code used to identify this catalog value or machine-readable result. (Maximum length: 10000 characters.) | `"Consulting services"` | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `modifierIds` | `string[]` | No | Yes | Ordered modifier identifiers applied to the record. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1J"]` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].code` | `string` | Yes | Yes | Stable machine-readable error or resource code. | `"Consulting services"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. | `"hour"` | | `data[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "code": "Consulting services", "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "Service fee", "value": "5" } ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert catalog entry **PUT** `/v1/entries/{entryId}` Create or update the addressed catalog entry. - Canonical URL: [https://docs.nqd.app/v1/reference/entries/upsert](https://docs.nqd.app/v1/reference/entries/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `entryId` | `string` | Yes | No | An opaque entry resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | No | Yes | Stable code used to identify this catalog value or machine-readable result. (Maximum length: 10000 characters.) | `"Consulting services"` | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `modifierIds` | `string[]` | No | Yes | Ordered modifier identifiers applied to the record. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1J"]` | ```json { "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.code` | `string` | Yes | Yes | Stable machine-readable error or resource code. | `"Consulting services"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.unitCode` | `string` | Yes | No | Unit code from the workspace catalog. | `"hour"` | | `data.quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "code": "Consulting services", "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "Service fee", "value": "5" } ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Archive catalog entry **DELETE** `/v1/entries/{entryId}` Archive catalog entry. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/entries/delete](https://docs.nqd.app/v1/reference/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `entryId` | `string` | Yes | No | An opaque entry resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1H failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert catalog entries in a batch **PUT** `/v1/entries` Upsert catalog entries atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/entries/bulk-upsert](https://docs.nqd.app/v1/reference/entries/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | No | Yes | Stable code used to identify this catalog value or machine-readable result. (Maximum length: 10000 characters.) | `"Consulting services"` | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `modifierIds` | `string[]` | No | Yes | Ordered modifier identifiers applied to the record. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1J"]` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].code` | `string` | Yes | Yes | Stable machine-readable error or resource code. | `"Consulting services"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. | `"hour"` | | `data[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "code": "Consulting services", "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "Service fee", "value": "5" } ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List expense templates **GET** `/v1/expenses/templates` Retrieve matching expense templates. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/list](https://docs.nqd.app/v1/reference/expenses/templates/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter expense-templates by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[vendorId]` | `string` | No | No | Filter expense-templates by vendorId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[clientId]` | `string` | No | No | Filter expense-templates by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[projectId]` | `string` | No | No | Filter expense-templates by projectId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `filter[bankAccountId]` | `string` | No | No | Filter expense-templates by bankAccountId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter expense-templates by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter expense-templates by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[notes]` | `string` | No | No | Filter expense-templates by notes. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter expense-templates by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[recurrenceMonths]` | `string` | No | No | Filter expense-templates by recurrenceMonths. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in operators) | `"eq.1"` | | `filter[createdBy]` | `string` | No | No | Filter expense-templates by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedBy]` | `string` | No | No | Filter expense-templates by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[deletedBy]` | `string` | No | No | Filter expense-templates by deletedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[amount]` | `string` | No | No | Filter expense-templates by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[startedAt]` | `string` | No | No | Filter expense-templates by startedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[endedAt]` | `string` | No | No | Filter expense-templates by endedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[nextDueAt]` | `string` | No | No | Filter expense-templates by nextDueAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter expense-templates by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter expense-templates by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedAt]` | `string` | No | No | Filter expense-templates by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[currencyId]` | `string` | No | No | Filter expense-templates by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter expense-templates by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,vendorId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,vendorId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `data[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this expense template. | `1` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this expense template. | `null` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"172.50"` | | `data[].totals` | `object` | Yes | No | totals for this expense template. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. | `"150.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"150.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"22.50"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"172.50"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"172.50"` | | `data[].totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. | `"172.50"` | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].vendorWebsite` | `string[]` | No | Yes | vendor website for this expense template. | `["https://example.com"]` | | `data[].projectWebsite` | `string` | No | Yes | project website for this expense template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this expense template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this expense template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].startedAt` | `string` | Yes | Yes | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "recurrenceMonths": 1, "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Create expense templates **POST** `/v1/expenses/templates` Create expense templates from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/create](https://docs.nqd.app/v1/reference/expenses/templates/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Office cleaning"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `notes` | `string` | Yes | No | Notes attached to the record. (Maximum length: 10000 characters.) | `"Office cleaning service for January 2026"` | | `vendorId` | `string` | Yes | No | ID of the related vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["office-supplies"]` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this expense template. (maximum 1200, greater than 0) | `1` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `startedAt` | `string` | Yes | Yes | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `data[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this expense template. | `1` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this expense template. | `null` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"172.50"` | | `data[].totals` | `object` | Yes | No | totals for this expense template. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. | `"150.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"150.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"22.50"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"172.50"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"172.50"` | | `data[].totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. | `"172.50"` | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].vendorWebsite` | `string[]` | No | Yes | vendor website for this expense template. | `["https://example.com"]` | | `data[].projectWebsite` | `string` | No | Yes | project website for this expense template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this expense template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this expense template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].startedAt` | `string` | Yes | Yes | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "recurrenceMonths": 1, "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/expenses/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Upsert expense template **PUT** `/v1/expenses/templates/{templateId}` Create or update the addressed expense template. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/upsert](https://docs.nqd.app/v1/reference/expenses/templates/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Office cleaning"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `notes` | `string` | Yes | No | Notes attached to the record. (Maximum length: 10000 characters.) | `"Office cleaning service for January 2026"` | | `vendorId` | `string` | Yes | No | ID of the related vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["office-supplies"]` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this expense template. (maximum 1200, greater than 0) | `1` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `startedAt` | `string` | Yes | Yes | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | ```json { "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `data.vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data.recurrenceMonths` | `number` | Yes | No | recurrence months for this expense template. | `1` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this expense template. | `null` | | `data.amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"172.50"` | | `data.totals` | `object` | Yes | No | totals for this expense template. | — | | `data.totals.base` | `string` | Yes | No | base within totals. | `"150.00"` | | `data.totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"150.00"` | | `data.totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"22.50"` | | `data.totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"172.50"` | | `data.totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"172.50"` | | `data.totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. | `"172.50"` | | `data.totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data.vendorWebsite` | `string[]` | No | Yes | vendor website for this expense template. | `["https://example.com"]` | | `data.projectWebsite` | `string` | No | Yes | project website for this expense template. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this expense template. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this expense template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.startedAt` | `string` | Yes | Yes | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data.endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data.nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "recurrenceMonths": 1, "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Delete expense template **DELETE** `/v1/expenses/templates/{templateId}` Delete expense template. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/delete](https://docs.nqd.app/v1/reference/expenses/templates/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Upsert expense templates in a batch **PUT** `/v1/expenses/templates` Upsert expense templates atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/bulk-upsert](https://docs.nqd.app/v1/reference/expenses/templates/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Office cleaning"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `notes` | `string` | Yes | No | Notes attached to the record. (Maximum length: 10000 characters.) | `"Office cleaning service for January 2026"` | | `vendorId` | `string` | Yes | No | ID of the related vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["office-supplies"]` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this expense template. (maximum 1200, greater than 0) | `1` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `startedAt` | `string` | Yes | Yes | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `data[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this expense template. | `1` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this expense template. | `null` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"172.50"` | | `data[].totals` | `object` | Yes | No | totals for this expense template. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. | `"150.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"150.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"22.50"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"172.50"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"172.50"` | | `data[].totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. | `"172.50"` | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].vendorWebsite` | `string[]` | No | Yes | vendor website for this expense template. | `["https://example.com"]` | | `data[].projectWebsite` | `string` | No | Yes | project website for this expense template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this expense template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this expense template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].startedAt` | `string` | Yes | Yes | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "recurrenceMonths": 1, "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Office cleaning", "description": "Monthly office cleaning service", "notes": "Office cleaning service for January 2026", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "bankAccountId": null, "tags": [ "office-supplies" ], "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # List applied entries for an expense template **GET** `/v1/expenses/templates/{templateId}/entries` Return the complete applied collection snapshot for an expense template. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/entries/list](https://docs.nqd.app/v1/reference/expenses/templates/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Add applied entry to an expense template **POST** `/v1/expenses/templates/{templateId}/entries` Add applied entry to an expense template and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/entries/create](https://docs.nqd.app/v1/reference/expenses/templates/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Office cleaning", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Office cleaning", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Office cleaning", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Partially update applied entry on an expense template **PATCH** `/v1/expenses/templates/{templateId}/entries/{entryId}` Partially update applied entry on an expense template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/entries/update](https://docs.nqd.app/v1/reference/expenses/templates/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Office cleaning" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Office cleaning" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Office cleaning" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Remove applied entry from an expense template **DELETE** `/v1/expenses/templates/{templateId}/entries/{entryId}` Remove applied entry from an expense template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/entries/delete](https://docs.nqd.app/v1/reference/expenses/templates/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Reorder applied entries for an expense template **PUT** `/v1/expenses/templates/{templateId}/entries/reorder` Replace the complete order of applied entries for an expense template and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/entries/reorder/upsert](https://docs.nqd.app/v1/reference/expenses/templates/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # List applied modifiers for an expense template **GET** `/v1/expenses/templates/{templateId}/modifiers` Return the complete applied collection snapshot for an expense template. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/modifiers/list](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Add applied modifier to an expense template **POST** `/v1/expenses/templates/{templateId}/modifiers` Add applied modifier to an expense template and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/modifiers/create](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `kind` | `string` | No | Yes | kind for this expense template. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this expense template. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this expense template. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Partially update applied modifier on an expense template **PATCH** `/v1/expenses/templates/{templateId}/modifiers/{modifierId}` Partially update applied modifier on an expense template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/modifiers/update](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `kind` | `string` | No | Yes | kind for this expense template. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this expense template. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this expense template. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Remove applied modifier from an expense template **DELETE** `/v1/expenses/templates/{templateId}/modifiers/{modifierId}` Remove applied modifier from an expense template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/modifiers/delete](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Reorder applied modifiers for an expense template **PUT** `/v1/expenses/templates/{templateId}/modifiers/reorder` Replace the complete order of applied modifiers for an expense template and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/templates/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/expenses/templates/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque expense_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1S" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1S" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1S" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1S/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # List expenses **GET** `/v1/expenses` Retrieve matching expenses. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/list](https://docs.nqd.app/v1/reference/expenses/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter expenses by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[vendorId]` | `string` | No | No | Filter expenses by vendorId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[clientId]` | `string` | No | No | Filter expenses by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[projectId]` | `string` | No | No | Filter expenses by projectId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `filter[expenseRecurringId]` | `string` | No | No | Filter expenses by expenseRecurringId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[bankAccountId]` | `string` | No | No | Filter expenses by bankAccountId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter expenses by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter expenses by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter expenses by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[amount]` | `string` | No | No | Filter expenses by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[notes]` | `string` | No | No | Filter expenses by notes. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[createdBy]` | `string` | No | No | Filter expenses by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedBy]` | `string` | No | No | Filter expenses by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[deletedBy]` | `string` | No | No | Filter expenses by deletedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[createdAt]` | `string` | No | No | Filter expenses by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter expenses by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedAt]` | `string` | No | No | Filter expenses by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[recurringOn]` | `string` | No | No | Filter expenses by recurringOn. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[currencyId]` | `string` | No | No | Filter expenses by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter expenses by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,vendorId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,vendorId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].expenseRecurringId` | `string` | Yes | Yes | ID of the related expense recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this expense. | `"Consulting services"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals` | `object` | Yes | No | totals for this expense. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. (Maximum length: 128 characters.) | `"150.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. (Maximum length: 128 characters.) | `"150.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. (Maximum length: 128 characters.) | `"22.50"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this expense. | `null` | | `data[].recurringOn` | `string` | Yes | Yes | recurring on for this expense. | `null` | | `data[].vendorWebsite` | `string[]` | No | Yes | vendor website for this expense. | `["https://example.com"]` | | `data[].projectWebsite` | `string` | No | Yes | project website for this expense. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this expense. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this expense. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "expenseRecurringId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "notes": "Office cleaning service for January 2026", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "recurringOn": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Retrieve expense **GET** `/v1/expenses/{expenseId}` Return the addressed expense. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/retrieve](https://docs.nqd.app/v1/reference/expenses/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data.vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.expenseRecurringId` | `string` | Yes | Yes | ID of the related expense recurring. | `null` | | `data.recurringSourceName` | `string` | No | Yes | recurring source name for this expense. | `"Consulting services"` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data.amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals` | `object` | Yes | No | totals for this expense. | — | | `data.totals.base` | `string` | Yes | No | base within totals. (Maximum length: 128 characters.) | `"150.00"` | | `data.totals.net` | `string` | Yes | No | Total before tax and other modifiers. (Maximum length: 128 characters.) | `"150.00"` | | `data.totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. (Maximum length: 128 characters.) | `"22.50"` | | `data.totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this expense. | `null` | | `data.recurringOn` | `string` | Yes | Yes | recurring on for this expense. | `null` | | `data.vendorWebsite` | `string[]` | No | Yes | vendor website for this expense. | `["https://example.com"]` | | `data.projectWebsite` | `string` | No | Yes | project website for this expense. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this expense. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this expense. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "expenseRecurringId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "notes": "Office cleaning service for January 2026", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "recurringOn": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Create expenses **POST** `/v1/expenses` Create outgoing payment expenses for a Vendor service from authored net entries and modifiers. The Vendor may be an individual or company; preserve exact decimal values and the selected currency. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/create](https://docs.nqd.app/v1/reference/expenses/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `vendorId` | `string` | Yes | No | ID of the related vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `expenseRecurringId` | `string` | No | Yes | ID of the related expense recurring. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `notes` | `string` | No | Yes | Notes attached to the record. (Maximum length: 10000 characters.) | `"Office cleaning service for January 2026"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["office-supplies"]` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"outbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].expenseRecurringId` | `string` | Yes | Yes | ID of the related expense recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this expense. | `"Consulting services"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals` | `object` | Yes | No | totals for this expense. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. (Maximum length: 128 characters.) | `"150.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. (Maximum length: 128 characters.) | `"150.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. (Maximum length: 128 characters.) | `"22.50"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this expense. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "expenseRecurringId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "notes": "Office cleaning service for January 2026", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/expenses failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. - Money is sent as an exact decimal string. Entry prices are net of VAT; the workspace payable modifier supplies the tax value. --- # Upsert expense **PUT** `/v1/expenses/{expenseId}` Upsert an outgoing Vendor-service expense with authored net entries and modifiers, preserving exact decimal values and the selected currency. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/upsert](https://docs.nqd.app/v1/reference/expenses/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `vendorId` | `string` | Yes | No | ID of the related vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `expenseRecurringId` | `string` | No | Yes | ID of the related expense recurring. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `notes` | `string` | No | Yes | Notes attached to the record. (Maximum length: 10000 characters.) | `"Office cleaning service for January 2026"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["office-supplies"]` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"outbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data.vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.expenseRecurringId` | `string` | Yes | Yes | ID of the related expense recurring. | `null` | | `data.recurringSourceName` | `string` | No | Yes | recurring source name for this expense. | `"Consulting services"` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data.amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals` | `object` | Yes | No | totals for this expense. | — | | `data.totals.base` | `string` | Yes | No | base within totals. (Maximum length: 128 characters.) | `"150.00"` | | `data.totals.net` | `string` | Yes | No | Total before tax and other modifiers. (Maximum length: 128 characters.) | `"150.00"` | | `data.totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. (Maximum length: 128 characters.) | `"22.50"` | | `data.totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. (Maximum length: 128 characters.) | `"172.50"` | | `data.totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this expense. | `null` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "expenseRecurringId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "notes": "Office cleaning service for January 2026", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete expense **DELETE** `/v1/expenses/{expenseId}` Delete expense. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/delete](https://docs.nqd.app/v1/reference/expenses/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Upsert expenses in a batch **PUT** `/v1/expenses` Upsert expenses atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/bulk-upsert](https://docs.nqd.app/v1/reference/expenses/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `vendorId` | `string` | Yes | No | ID of the related vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `expenseRecurringId` | `string` | No | Yes | ID of the related expense recurring. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `notes` | `string` | No | Yes | Notes attached to the record. (Maximum length: 10000 characters.) | `"Office cleaning service for January 2026"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["office-supplies"]` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"outbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].expenseRecurringId` | `string` | Yes | Yes | ID of the related expense recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this expense. | `"Consulting services"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Office cleaning"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Monthly office cleaning service"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Office cleaning"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["office-supplies"]` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals` | `object` | Yes | No | totals for this expense. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. (Maximum length: 128 characters.) | `"150.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. (Maximum length: 128 characters.) | `"150.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. (Maximum length: 128 characters.) | `"22.50"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.reporting` | `string` | Yes | No | Amount converted to the workspace reporting currency. (Maximum length: 128 characters.) | `"172.50"` | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Office cleaning service for January 2026"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this expense. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "projectId": null, "expenseRecurringId": null, "bankAccountId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "office-supplies" ], "amount": "172.50", "totals": { "base": "150.00", "net": "150.00", "tax": "22.50", "gross": "172.50", "payable": "172.50", "reporting": "172.50", "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "150.00" } }, "notes": "Office cleaning service for January 2026", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Office cleaning", "description": "Monthly office cleaning service", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Office cleaning", "description": "Monthly office cleaning service", "quantity": "3.00", "unit": "item", "pricePerUnit": "50.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List applied entries for an expense **GET** `/v1/expenses/{expenseId}/entries` Return the complete applied collection snapshot for an expense. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/entries/list](https://docs.nqd.app/v1/reference/expenses/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Add applied entry to an expense **POST** `/v1/expenses/{expenseId}/entries` Add applied entry to an expense and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/entries/create](https://docs.nqd.app/v1/reference/expenses/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Office cleaning", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Office cleaning", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Office cleaning", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Partially update applied entry on an expense **PATCH** `/v1/expenses/{expenseId}/entries/{entryId}` Partially update applied entry on an expense and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/entries/update](https://docs.nqd.app/v1/reference/expenses/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Office cleaning" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Office cleaning", "description": "Monthly office cleaning service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Office cleaning" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Office cleaning" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied entry from an expense **DELETE** `/v1/expenses/{expenseId}/entries/{entryId}` Remove applied entry from an expense and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/entries/delete](https://docs.nqd.app/v1/reference/expenses/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Reorder applied entries for an expense **PUT** `/v1/expenses/{expenseId}/entries/reorder` Replace the complete order of applied entries for an expense and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/entries/reorder/upsert](https://docs.nqd.app/v1/reference/expenses/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # List applied modifiers for an expense **GET** `/v1/expenses/{expenseId}/modifiers` Return the complete applied collection snapshot for an expense. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/modifiers/list](https://docs.nqd.app/v1/reference/expenses/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Add applied modifier to an expense **POST** `/v1/expenses/{expenseId}/modifiers` Add applied modifier to an expense and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/modifiers/create](https://docs.nqd.app/v1/reference/expenses/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `kind` | `string` | No | Yes | kind for this expense. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this expense. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this expense. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Partially update applied modifier on an expense **PATCH** `/v1/expenses/{expenseId}/modifiers/{modifierId}` Partially update applied modifier on an expense and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/modifiers/update](https://docs.nqd.app/v1/reference/expenses/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `kind` | `string` | No | Yes | kind for this expense. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this expense. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this expense. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied modifier from an expense **DELETE** `/v1/expenses/{expenseId}/modifiers/{modifierId}` Remove applied modifier from an expense and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/modifiers/delete](https://docs.nqd.app/v1/reference/expenses/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # Reorder applied modifiers for an expense **PUT** `/v1/expenses/{expenseId}/modifiers/reorder` Replace the complete order of applied modifiers for an expense and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/expenses/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expenseId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1R" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Office cleaning"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly office cleaning service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"item"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"3.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"50.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Office cleaning", "description": "Monthly office cleaning service", "unitCode": "item", "quantity": "3.00", "pricePerUnit": "50.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1R" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1R" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Expense is an outgoing payment source for a Vendor's service, whether that Vendor is an individual or a company. Client and Project are optional; a null Client means the current Workspace. Record cash separately through Transactions. --- # List transactions **GET** `/v1/expenses/{sourceId}/transactions` Retrieve matching transactions. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/transactions/list](https://docs.nqd.app/v1/reference/expenses/transactions/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter expenses by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[amount]` | `string` | No | No | Filter expenses by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[direction]` | `string` | No | No | Filter expenses by direction. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.inbound"` | | `filter[createdAt]` | `string` | No | No | Filter expenses by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[bankAccountId]` | `string` | No | No | Filter expenses by bankAccountId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[originalId]` | `string` | No | No | Filter expenses by originalId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceId]` | `string` | No | No | Filter expenses by sourceId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceType]` | `string` | No | No | Filter expenses by sourceType. Use operator.value syntax. (eq, neq, in operators) | `"eq.invoice"` | | `filter[currencyCode]` | `string` | No | No | Filter expenses by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,source"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,amount.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data[].source` | `object` | Yes | Yes | source for this expense. | — | | `data[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].direction` | `string` | Yes | No | direction for this expense. (Allowed values: "inbound", "outbound") | `"outbound"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].accountLabel` | `string` | No | Yes | account label for this expense. | `"Consulting services"` | | `data[].originalId` | `string` | Yes | Yes | ID of the related original. | `"Consulting services"` | | `data[].context` | `object` | Yes | No | context for this expense. | — | | `data[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "type": "invoice" }, "amount": "100.00", "direction": "outbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "bankAccountId": null, "originalId": "Consulting services", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # Record a payment **POST** `/v1/expenses/{sourceId}/transactions` Record a payment against the source using its currency and the selected or default bank account. - Canonical URL: [https://docs.nqd.app/v1/reference/expenses/transactions/create](https://docs.nqd.app/v1/reference/expenses/transactions/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque expense resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this expense. | `true` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": true } } ``` ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this expense. | `false` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": false } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/expenses/01JQ2T5Y5Q3R8W9N6M4K2H7P1R/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. - The payment uses the source currency and the selected or configured workspace bank account; validate conversion when currencies differ. --- # Update the workspace fiscal year **PUT** `/v1/settings/fiscal-year` Update the workspace fiscal year. - Canonical URL: [https://docs.nqd.app/v1/reference/settings/fiscal-year/upsert](https://docs.nqd.app/v1/reference/settings/fiscal-year/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `value` | `string` | Yes | Yes | Value returned by the operation. | `"2026-01-01"` | ```json { "value": "2026-01-01" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Acme workspace"` | | `data.slug` | `string` | Yes | No | slug for this fiscal year. | `"acme-workspace"` | | `data.officialName` | `string` | Yes | Yes | official name for this fiscal year. | `"Consulting services"` | | `data.tradeName` | `string` | Yes | Yes | trade name for this fiscal year. | `"Consulting services"` | | `data.registrationNumber` | `string` | Yes | Yes | registration number for this fiscal year. | `"CR-0001234567"` | | `data.taxId` | `string` | Yes | Yes | ID of the related tax. | `"100.00"` | | `data.defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. | `null` | | `data.defaultInvoiceBankAccountId` | `string` | Yes | Yes | ID of the related default invoice bank account. | `null` | | `data.defaultIncomeBankAccountId` | `string` | Yes | Yes | ID of the related default income bank account. | `null` | | `data.defaultAssetBankAccountId` | `string` | Yes | Yes | ID of the related default asset bank account. | `null` | | `data.defaultExpenseBankAccountId` | `string` | Yes | Yes | ID of the related default expense bank account. | `null` | | `data.defaultPayoutBankAccountId` | `string` | Yes | Yes | ID of the related default payout bank account. | `null` | | `data.defaultExpenseRecurringBankAccountId` | `string` | Yes | Yes | ID of the related default expense recurring bank account. | `null` | | `data.email` | `string` | Yes | Yes | Email address associated with the identity. | `"owner@example.com"` | | `data.phone` | `string` | Yes | Yes | phone for this fiscal year. | `"+966500000000"` | | `data.address` | `string` | Yes | Yes | address for this fiscal year. | `"King Fahd Road"` | | `data.city` | `string` | Yes | Yes | city for this fiscal year. | `"Riyadh"` | | `data.state` | `string` | Yes | Yes | Current state of the record or operation. | `"Riyadh"` | | `data.postalCode` | `string` | Yes | Yes | postal code for this fiscal year. | `"Consulting services"` | | `data.country` | `string` | Yes | Yes | country for this fiscal year. | `"SA"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this fiscal year. | `null` | | `data.fiscalYearStartAt` | `string` | Yes | Yes | ISO 8601 timestamp for fiscal year start. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1A", "name": "Acme workspace", "slug": "acme-workspace", "officialName": "Consulting services", "tradeName": "Consulting services", "registrationNumber": "CR-0001234567", "taxId": "100.00", "defaultCurrencyId": null, "defaultInvoiceBankAccountId": null, "defaultIncomeBankAccountId": null, "defaultAssetBankAccountId": null, "defaultExpenseBankAccountId": null, "defaultPayoutBankAccountId": null, "defaultExpenseRecurringBankAccountId": null, "email": "owner@example.com", "phone": "+966500000000", "address": "King Fahd Road", "city": "Riyadh", "state": "Riyadh", "postalCode": "Consulting services", "country": "SA", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "fiscalYearStartAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/settings/fiscal-year" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "value": "2026-01-01" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/settings/fiscal-year", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "value": "2026-01-01" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/settings/fiscal-year failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List income records **GET** `/v1/income` Retrieve matching income records. - Canonical URL: [https://docs.nqd.app/v1/reference/income/list](https://docs.nqd.app/v1/reference/income/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter income by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter income by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter income by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[clientId]` | `string` | No | No | Filter income by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[projectId]` | `string` | No | No | Filter income by projectId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `filter[contactId]` | `string` | No | No | Filter income by contactId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `filter[bankAccountId]` | `string` | No | No | Filter income by bankAccountId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[tags]` | `string` | No | No | Filter income by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[createdBy]` | `string` | No | No | Filter income by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedBy]` | `string` | No | No | Filter income by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[createdAt]` | `string` | No | No | Filter income by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter income by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[currencyId]` | `string` | No | No | Filter income by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter income by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `filter[amount]` | `string` | No | No | Filter income by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Product sale"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Product receipt for January 2026"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Product sale"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].totals` | `object` | Yes | No | totals for this income. | — | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. | `"400.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"400.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"60.00"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"460.00"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"460.00"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W", "name": "Product sale", "description": "Product receipt for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "400.00" }, "base": "400.00", "net": "400.00", "tax": "60.00", "gross": "460.00", "payable": "460.00" }, "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/income failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Retrieve income record **GET** `/v1/income/{incomeId}` Return the addressed income record. - Canonical URL: [https://docs.nqd.app/v1/reference/income/retrieve](https://docs.nqd.app/v1/reference/income/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Product sale"` | | `data.description` | `string` | Yes | No | Optional human-readable description of the record. | `"Product receipt for January 2026"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.totals` | `object` | Yes | No | totals for this income. | — | | `data.totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data.totals.base` | `string` | Yes | No | base within totals. | `"400.00"` | | `data.totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"400.00"` | | `data.totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"60.00"` | | `data.totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"460.00"` | | `data.totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"460.00"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W", "name": "Product sale", "description": "Product receipt for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "400.00" }, "base": "400.00", "net": "400.00", "tax": "60.00", "gross": "460.00", "payable": "460.00" }, "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Create income records **POST** `/v1/income` Create standalone incoming cash income, such as capital, inheritance, or product receipts. A buyer Client is optional; service work belongs in an Invoice. - Canonical URL: [https://docs.nqd.app/v1/reference/income/create](https://docs.nqd.app/v1/reference/income/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Product sale"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Product sale"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | No | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Product sale"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ] } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Product sale"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Product receipt for January 2026"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Product sale"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].totals` | `object` | Yes | No | totals for this income. | — | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. | `"400.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"400.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"60.00"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"460.00"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"460.00"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W", "name": "Product sale", "description": "Product receipt for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "400.00" }, "base": "400.00", "net": "400.00", "tax": "60.00", "gross": "460.00", "payable": "460.00" }, "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ] } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ] } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/income failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Upsert income record **PUT** `/v1/income/{incomeId}` Upsert standalone incoming cash income, preserving authored net entries, modifiers, exact decimal values, and selected currency. - Canonical URL: [https://docs.nqd.app/v1/reference/income/upsert](https://docs.nqd.app/v1/reference/income/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Product sale"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Product sale"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | No | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Product sale"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Product sale"` | | `data.description` | `string` | Yes | No | Optional human-readable description of the record. | `"Product receipt for January 2026"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.totals` | `object` | Yes | No | totals for this income. | — | | `data.totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data.totals.base` | `string` | Yes | No | base within totals. | `"400.00"` | | `data.totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"400.00"` | | `data.totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"60.00"` | | `data.totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"460.00"` | | `data.totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"460.00"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W", "name": "Product sale", "description": "Product receipt for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "400.00" }, "base": "400.00", "net": "400.00", "tax": "60.00", "gross": "460.00", "payable": "460.00" }, "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete income record **DELETE** `/v1/income/{incomeId}` Delete income record. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/income/delete](https://docs.nqd.app/v1/reference/income/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Upsert income records in a batch **PUT** `/v1/income` Upsert income records atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/income/bulk-upsert](https://docs.nqd.app/v1/reference/income/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Product sale"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Product sale"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | No | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `tags` | `string[]` | Yes | No | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Product sale"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Product sale"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Product receipt for January 2026"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Product sale"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].totals` | `object` | Yes | No | totals for this income. | — | | `data[].totals.lineTotals` | `object` | Yes | No | line totals within totals. | — | | `data[].totals.base` | `string` | Yes | No | base within totals. | `"400.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"400.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"60.00"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"460.00"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"460.00"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | No | Identifier of the identity that last updated the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | No | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W", "name": "Product sale", "description": "Product receipt for January 2026", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "400.00" }, "base": "400.00", "net": "400.00", "tax": "60.00", "gross": "460.00", "payable": "460.00" }, "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Product sale", "description": "Product receipt for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Product sale", "description": "Product receipt for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "200.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "tags": [ "equipment" ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/income failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List applied entries for an income record **GET** `/v1/income/{incomeId}/entries` Return the complete applied collection snapshot for an income record. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/income/entries/list](https://docs.nqd.app/v1/reference/income/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Add applied entry to an income record **POST** `/v1/income/{incomeId}/entries` Add applied entry to an income record and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/income/entries/create](https://docs.nqd.app/v1/reference/income/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Product sale", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Product sale", "description": "Product receipt for January 2026", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Product sale", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Product sale", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Partially update applied entry on an income record **PATCH** `/v1/income/{incomeId}/entries/{entryId}` Partially update applied entry on an income record and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/income/entries/update](https://docs.nqd.app/v1/reference/income/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Product sale" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Product sale", "description": "Product receipt for January 2026", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Product sale" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Product sale" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied entry from an income record **DELETE** `/v1/income/{incomeId}/entries/{entryId}` Remove applied entry from an income record and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/income/entries/delete](https://docs.nqd.app/v1/reference/income/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Reorder applied entries for an income record **PUT** `/v1/income/{incomeId}/entries/reorder` Replace the complete order of applied entries for an income record and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/income/entries/reorder/upsert](https://docs.nqd.app/v1/reference/income/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # List applied modifiers for an income record **GET** `/v1/income/{incomeId}/modifiers` Return the complete applied collection snapshot for an income record. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/income/modifiers/list](https://docs.nqd.app/v1/reference/income/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "200.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Add applied modifier to an income record **POST** `/v1/income/{incomeId}/modifiers` Add applied modifier to an income record and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/income/modifiers/create](https://docs.nqd.app/v1/reference/income/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `kind` | `string` | No | Yes | kind for this income. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this income. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this income. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "200.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Partially update applied modifier on an income record **PATCH** `/v1/income/{incomeId}/modifiers/{modifierId}` Partially update applied modifier on an income record and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/income/modifiers/update](https://docs.nqd.app/v1/reference/income/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `kind` | `string` | No | Yes | kind for this income. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this income. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this income. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "200.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied modifier from an income record **DELETE** `/v1/income/{incomeId}/modifiers/{modifierId}` Remove applied modifier from an income record and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/income/modifiers/delete](https://docs.nqd.app/v1/reference/income/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # Reorder applied modifiers for an income record **PUT** `/v1/income/{incomeId}/modifiers/reorder` Replace the complete order of applied modifiers for an income record and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/income/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/income/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `incomeId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1W"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1W" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Product sale"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Product receipt for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"200.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Product sale"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Product sale", "name": "Product sale", "description": "Product receipt for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "200.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Product sale", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1W" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1W" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Income is an incoming cash source that does not require a service-work relationship. Use it for capital, inheritance, product receipts, or other standalone receipts. A buyer Client is optional. Record cash separately through Transactions. --- # List transactions **GET** `/v1/income/{sourceId}/transactions` Retrieve matching transactions. - Canonical URL: [https://docs.nqd.app/v1/reference/income/transactions/list](https://docs.nqd.app/v1/reference/income/transactions/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter income by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[amount]` | `string` | No | No | Filter income by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[direction]` | `string` | No | No | Filter income by direction. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.inbound"` | | `filter[createdAt]` | `string` | No | No | Filter income by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[bankAccountId]` | `string` | No | No | Filter income by bankAccountId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[originalId]` | `string` | No | No | Filter income by originalId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceId]` | `string` | No | No | Filter income by sourceId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceType]` | `string` | No | No | Filter income by sourceType. Use operator.value syntax. (eq, neq, in operators) | `"eq.invoice"` | | `filter[currencyCode]` | `string` | No | No | Filter income by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,source"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,amount.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `data[].source` | `object` | Yes | Yes | source for this income. | — | | `data[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | | `data[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].direction` | `string` | Yes | No | direction for this income. (Allowed values: "inbound", "outbound") | `"inbound"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].accountLabel` | `string` | No | Yes | account label for this income. | `"Product sale"` | | `data[].originalId` | `string` | Yes | Yes | ID of the related original. | `"Product sale"` | | `data[].context` | `object` | Yes | No | context for this income. | — | | `data[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1W", "type": "invoice" }, "amount": "100.00", "direction": "inbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "bankAccountId": null, "originalId": "Product sale", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # Record a payment **POST** `/v1/income/{sourceId}/transactions` Record a payment against the source using its currency and the selected or default bank account. - Canonical URL: [https://docs.nqd.app/v1/reference/income/transactions/create](https://docs.nqd.app/v1/reference/income/transactions/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque income resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1W"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this income. | `true` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": true } } ``` ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this income. | `false` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": false } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/income/01JQ2T5Y5Q3R8W9N6M4K2H7P1W/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. - The payment uses the source currency and the selected or configured workspace bank account; validate conversion when currencies differ. --- # Create workspace participant **POST** `/v1/invitations` Create workspace participant from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/invitations/create](https://docs.nqd.app/v1/reference/invitations/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `email` | `string` | Yes | No | Email address associated with the identity. (Maximum length: 2048 characters.) | `"owner@example.com"` | | `role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | ```json { "email": "owner@example.com", "role": "owner" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. Alternatives: object alternative 1, object alternative 2. | — | | `data.member` | `object` | Yes | Yes | member for this invitation. Applies to object alternative 1. | — | | `data.member.profileId` | `string` | Yes | No | ID of the related profile. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.member.username` | `string` | Yes | No | username within member. | `"owner"` | | `data.member.email` | `string` | Yes | No | Email address associated with the identity. | `"owner@example.com"` | | `data.member.role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | | `data.invite` | `object` | Yes | No | invite for this invitation. Applies to object alternative 2. | — | | `data.invite.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2C"` | | `data.invite.email` | `string` | Yes | No | Email address associated with the identity. | `"owner@example.com"` | | `data.invite.role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | | `data.invite.invitedAt` | `string` | Yes | No | ISO 8601 timestamp for invited. | `"2026-01-15T12:00:00.000Z"` | | `data.invite.expiresAt` | `string` | Yes | Yes | ISO 8601 timestamp when the invitation expires. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "member": { "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "username": "owner", "email": "owner@example.com", "role": "owner" } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invitations" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "email": "owner@example.com", "role": "owner" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invitations", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "email": "owner@example.com", "role": "owner" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invitations failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Revoke workspace participant **DELETE** `/v1/invitations/{inviteId}` Revoke workspace participant. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/invitations/delete](https://docs.nqd.app/v1/reference/invitations/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `inviteId` | `string` | Yes | No | An opaque workspace_invite resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2C"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invitations/01JQ2T5Y5Q3R8W9N6M4K2H7P2C" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invitations/01JQ2T5Y5Q3R8W9N6M4K2H7P2C", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/invitations/01JQ2T5Y5Q3R8W9N6M4K2H7P2C failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Resend a workspace invitation **POST** `/v1/invitations/{inviteId}/redeliveries` Resend a workspace invitation. - Canonical URL: [https://docs.nqd.app/v1/reference/invitations/redeliveries/create](https://docs.nqd.app/v1/reference/invitations/redeliveries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `inviteId` | `string` | Yes | No | An opaque workspace_invite resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2C"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.invite` | `object` | Yes | Yes | invite for this invitation. | — | | `data.invite.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2C"` | | `data.invite.email` | `string` | Yes | No | Email address associated with the identity. | `"owner@example.com"` | | `data.invite.role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | | `data.invite.invitedAt` | `string` | Yes | No | ISO 8601 timestamp for invited. | `"2026-01-15T12:00:00.000Z"` | | `data.invite.expiresAt` | `string` | Yes | Yes | ISO 8601 timestamp when the invitation expires. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "invite": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P2C", "email": "owner@example.com", "role": "owner", "invitedAt": "2026-01-15T12:00:00.000Z", "expiresAt": "2026-01-15T12:00:00.000Z" } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invitations/01JQ2T5Y5Q3R8W9N6M4K2H7P2C/redeliveries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invitations/01JQ2T5Y5Q3R8W9N6M4K2H7P2C/redeliveries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invitations/01JQ2T5Y5Q3R8W9N6M4K2H7P2C/redeliveries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Accept pending workspace invitations **POST** `/v1/invitations/acceptances` Accept pending workspace invitations. - Canonical URL: [https://docs.nqd.app/v1/reference/invitations/acceptances/create](https://docs.nqd.app/v1/reference/invitations/acceptances/create) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.accepted` | `number` | Yes | No | accepted for this invitation. | `100` | ```json { "data": { "accepted": 100 } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invitations/acceptances" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invitations/acceptances", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invitations/acceptances failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Writes are atomic. If a response is lost, read the resource before retrying. --- # List pending workspace invitations **GET** `/v1/invitations/pending` List pending workspace invitations. - Canonical URL: [https://docs.nqd.app/v1/reference/invitations/pending](https://docs.nqd.app/v1/reference/invitations/pending) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.pending` | `boolean` | Yes | No | pending for this invitation. | `true` | ```json { "data": { "pending": true } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invitations/pending" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invitations/pending", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invitations/pending failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List invoice templates **GET** `/v1/invoices/templates` Retrieve matching invoice templates. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/list](https://docs.nqd.app/v1/reference/invoices/templates/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter invoice-templates by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[clientId]` | `string` | No | No | Filter invoice-templates by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[projectId]` | `string` | No | No | Filter invoice-templates by projectId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `filter[contactId]` | `string` | No | No | Filter invoice-templates by contactId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `filter[bankAccountId]` | `string` | No | No | Filter invoice-templates by bankAccountId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter invoice-templates by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter invoice-templates by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[notes]` | `string` | No | No | Filter invoice-templates by notes. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[recurrenceMonths]` | `string` | No | No | Filter invoice-templates by recurrenceMonths. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in operators) | `"eq.1"` | | `filter[tags]` | `string` | No | No | Filter invoice-templates by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[startedAt]` | `string` | No | No | Filter invoice-templates by startedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[endedAt]` | `string` | No | No | Filter invoice-templates by endedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[nextDueAt]` | `string` | No | No | Filter invoice-templates by nextDueAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter invoice-templates by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdBy]` | `string` | No | No | Filter invoice-templates by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedAt]` | `string` | No | No | Filter invoice-templates by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedBy]` | `string` | No | No | Filter invoice-templates by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[deletedAt]` | `string` | No | No | Filter invoice-templates by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedBy]` | `string` | No | No | Filter invoice-templates by deletedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[currencyId]` | `string` | No | No | Filter invoice-templates by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter invoice-templates by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,currency"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,clientId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].contactId` | `string` | Yes | No | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data[].projectWebsite` | `string` | No | Yes | project website for this invoice template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this invoice template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this invoice template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this invoice template. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Consulting services"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].notes` | `string` | Yes | No | Notes attached to the record. | `"Consulting services"` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this invoice template. | `1` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this invoice template. | `null` | | `data[].startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Create invoice templates **POST** `/v1/invoices/templates` Create invoice templates from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/create](https://docs.nqd.app/v1/reference/invoices/templates/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | No | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | Yes | No | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting services"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `notes` | `string` | Yes | No | Notes attached to the record. (Maximum length: 10000 characters.) | `"Consulting services"` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this invoice template. (maximum 1200, greater than 0) | `1` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting service"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].contactId` | `string` | Yes | No | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data[].projectWebsite` | `string` | No | Yes | project website for this invoice template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this invoice template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this invoice template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this invoice template. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Consulting services"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].notes` | `string` | Yes | No | Notes attached to the record. | `"Consulting services"` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this invoice template. | `1` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this invoice template. | `null` | | `data[].startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invoices/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Upsert invoice template **PUT** `/v1/invoices/templates/{templateId}` Create or update the addressed invoice template. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/upsert](https://docs.nqd.app/v1/reference/invoices/templates/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | No | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | Yes | No | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting services"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `notes` | `string` | Yes | No | Notes attached to the record. (Maximum length: 10000 characters.) | `"Consulting services"` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this invoice template. (maximum 1200, greater than 0) | `1` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting service"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | ```json { "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.contactId` | `string` | Yes | No | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data.projectWebsite` | `string` | No | Yes | project website for this invoice template. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this invoice template. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this invoice template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.contactWebsite` | `string[]` | No | Yes | contact website for this invoice template. | `["https://example.com"]` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Consulting services"` | | `data.description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.notes` | `string` | Yes | No | Notes attached to the record. | `"Consulting services"` | | `data.recurrenceMonths` | `number` | Yes | No | recurrence months for this invoice template. | `1` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this invoice template. | `null` | | `data.startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data.endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data.nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Delete invoice template **DELETE** `/v1/invoices/templates/{templateId}` Delete invoice template. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/delete](https://docs.nqd.app/v1/reference/invoices/templates/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Upsert invoice templates in a batch **PUT** `/v1/invoices/templates` Upsert invoice templates atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/bulk-upsert](https://docs.nqd.app/v1/reference/invoices/templates/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | No | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | Yes | No | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting services"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `notes` | `string` | Yes | No | Notes attached to the record. (Maximum length: 10000 characters.) | `"Consulting services"` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this invoice template. (maximum 1200, greater than 0) | `1` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting service"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].contactId` | `string` | Yes | No | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `data[].projectWebsite` | `string` | No | Yes | project website for this invoice template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this invoice template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this invoice template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this invoice template. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Consulting services"` | | `data[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].notes` | `string` | Yes | No | Notes attached to the record. | `"Consulting services"` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this invoice template. | `1` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this invoice template. | `null` | | `data[].startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "clientId": null, "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1E", "bankAccountId": null, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "recurrenceMonths": 1, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # List applied entries for an invoice template **GET** `/v1/invoices/templates/{templateId}/entries` Return the complete applied collection snapshot for an invoice template. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/entries/list](https://docs.nqd.app/v1/reference/invoices/templates/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Add applied entry to an invoice template **POST** `/v1/invoices/templates/{templateId}/entries` Add applied entry to an invoice template and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/entries/create](https://docs.nqd.app/v1/reference/invoices/templates/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Consulting service", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Consulting service", "description": "Monthly consulting service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Consulting service", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Consulting service", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Partially update applied entry on an invoice template **PATCH** `/v1/invoices/templates/{templateId}/entries/{entryId}` Partially update applied entry on an invoice template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/entries/update](https://docs.nqd.app/v1/reference/invoices/templates/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Consulting service" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Consulting service", "description": "Monthly consulting service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Consulting service" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Consulting service" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Remove applied entry from an invoice template **DELETE** `/v1/invoices/templates/{templateId}/entries/{entryId}` Remove applied entry from an invoice template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/entries/delete](https://docs.nqd.app/v1/reference/invoices/templates/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Reorder applied entries for an invoice template **PUT** `/v1/invoices/templates/{templateId}/entries/reorder` Replace the complete order of applied entries for an invoice template and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/entries/reorder/upsert](https://docs.nqd.app/v1/reference/invoices/templates/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # List applied modifiers for an invoice template **GET** `/v1/invoices/templates/{templateId}/modifiers` Return the complete applied collection snapshot for an invoice template. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/modifiers/list](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Add applied modifier to an invoice template **POST** `/v1/invoices/templates/{templateId}/modifiers` Add applied modifier to an invoice template and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/modifiers/create](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `kind` | `string` | No | Yes | kind for this invoice template. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this invoice template. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this invoice template. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Partially update applied modifier on an invoice template **PATCH** `/v1/invoices/templates/{templateId}/modifiers/{modifierId}` Partially update applied modifier on an invoice template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/modifiers/update](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `kind` | `string` | No | Yes | kind for this invoice template. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this invoice template. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this invoice template. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Remove applied modifier from an invoice template **DELETE** `/v1/invoices/templates/{templateId}/modifiers/{modifierId}` Remove applied modifier from an invoice template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/modifiers/delete](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Reorder applied modifiers for an invoice template **PUT** `/v1/invoices/templates/{templateId}/modifiers/reorder` Replace the complete order of applied modifiers for an invoice template and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/templates/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/invoices/templates/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque invoice_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1Q"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1Q" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1Q/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # List invoices **GET** `/v1/invoices` Retrieve matching invoices. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/list](https://docs.nqd.app/v1/reference/invoices/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter invoices by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[shortId]` | `string` | No | No | Filter invoices by shortId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[clientId]` | `string` | No | No | Filter invoices by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[projectId]` | `string` | No | No | Filter invoices by projectId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `filter[contactId]` | `string` | No | No | Filter invoices by contactId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `filter[bankAccountId]` | `string` | No | No | Filter invoices by bankAccountId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[invoiceRecurringId]` | `string` | No | No | Filter invoices by invoiceRecurringId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter invoices by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter invoices by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[notes]` | `string` | No | No | Filter invoices by notes. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter invoices by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[settled]` | `string` | No | No | Filter invoices by settled. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.true"` | | `filter[pendedAt]` | `string` | No | No | Filter invoices by pendedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[cancelledAt]` | `string` | No | No | Filter invoices by cancelledAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter invoices by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdBy]` | `string` | No | No | Filter invoices by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedAt]` | `string` | No | No | Filter invoices by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedBy]` | `string` | No | No | Filter invoices by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[deletedAt]` | `string` | No | No | Filter invoices by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedBy]` | `string` | No | No | Filter invoices by deletedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[currencyId]` | `string` | No | No | Filter invoices by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter invoices by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `filter[amount]` | `string` | No | No | Filter invoices by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[activityAt]` | `string` | No | No | Filter invoices by activityAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[status]` | `string` | No | No | Filter invoices by status. Use operator.value syntax. (eq, neq, in operators) | `"eq.draft"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,shortId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,shortId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data[].shortId` | `string` | Yes | No | ID of the related short. | `"INV-0001"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this invoice. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this invoice. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this invoice. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this invoice. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].invoiceRecurringId` | `string` | Yes | Yes | ID of the related invoice recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this invoice. | `"Consulting services"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Consulting services"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].totals` | `object` | No | Yes | totals for this invoice. | — | | `data[].totals.lineTotals` | `object` | No | Yes | line totals within totals. | — | | `data[].totals.base` | `string` | No | Yes | base within totals. | `"200.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"200.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"30.00"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"230.00"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"230.00"` | | `data[].totals.reporting` | `string` | No | Yes | Amount converted to the workspace reporting currency. | `"230.00"` | | `data[].recurringOn` | `string` | No | Yes | recurring on for this invoice. | `"2026-01-15"` | | `data[].settled` | `boolean` | No | Yes | Whether effective transactions cover the amount due. | `false` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this invoice. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data[].cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "shortId": "INV-0001", "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "invoiceRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "200.00" }, "base": "200.00", "net": "200.00", "tax": "30.00", "gross": "230.00", "payable": "230.00", "reporting": "230.00" }, "pendedAt": null, "cancelledAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Retrieve invoice **GET** `/v1/invoices/{invoiceId}` Return the addressed invoice. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/retrieve](https://docs.nqd.app/v1/reference/invoices/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.shortId` | `string` | Yes | No | ID of the related short. | `"INV-0001"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data.projectWebsite` | `string` | No | Yes | project website for this invoice. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this invoice. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this invoice. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.contactWebsite` | `string[]` | No | Yes | contact website for this invoice. | `["https://example.com"]` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.invoiceRecurringId` | `string` | Yes | Yes | ID of the related invoice recurring. | `null` | | `data.recurringSourceName` | `string` | No | Yes | recurring source name for this invoice. | `"Consulting services"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"Consulting services"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.totals` | `object` | No | Yes | totals for this invoice. | — | | `data.totals.lineTotals` | `object` | No | Yes | line totals within totals. | — | | `data.totals.base` | `string` | No | Yes | base within totals. | `"200.00"` | | `data.totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"200.00"` | | `data.totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"30.00"` | | `data.totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"230.00"` | | `data.totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"230.00"` | | `data.totals.reporting` | `string` | No | Yes | Amount converted to the workspace reporting currency. | `"230.00"` | | `data.recurringOn` | `string` | No | Yes | recurring on for this invoice. | `"2026-01-15"` | | `data.settled` | `boolean` | No | Yes | Whether effective transactions cover the amount due. | `false` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this invoice. | `null` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data.cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "shortId": "INV-0001", "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "invoiceRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "200.00" }, "base": "200.00", "net": "200.00", "tax": "30.00", "gross": "230.00", "payable": "230.00", "reporting": "230.00" }, "pendedAt": null, "cancelledAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Create invoices **POST** `/v1/invoices` Create incoming service invoices from authored net entries and modifiers. Use Client and Project for service context; preserve exact decimal values and the selected currency. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/create](https://docs.nqd.app/v1/reference/invoices/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | No | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `name` | `string` | No | Yes | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting services"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting service"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `pendedAt` | `string` | No | Yes | ISO 8601 timestamp for pended. | `"2026-01-15T12:00:00.000Z"` | | `cancelledAt` | `string` | No | Yes | ISO 8601 timestamp for cancelled. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data[].shortId` | `string` | Yes | No | ID of the related short. | `"INV-0001"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this invoice. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this invoice. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this invoice. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this invoice. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].invoiceRecurringId` | `string` | Yes | Yes | ID of the related invoice recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this invoice. | `"Consulting services"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Consulting services"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].totals` | `object` | No | Yes | totals for this invoice. | — | | `data[].totals.lineTotals` | `object` | No | Yes | line totals within totals. | — | | `data[].totals.base` | `string` | No | Yes | base within totals. | `"200.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"200.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"30.00"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"230.00"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"230.00"` | | `data[].totals.reporting` | `string` | No | Yes | Amount converted to the workspace reporting currency. | `"230.00"` | | `data[].recurringOn` | `string` | No | Yes | recurring on for this invoice. | `"2026-01-15"` | | `data[].settled` | `boolean` | No | Yes | Whether effective transactions cover the amount due. | `false` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this invoice. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data[].cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "shortId": "INV-0001", "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "invoiceRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "200.00" }, "base": "200.00", "net": "200.00", "tax": "30.00", "gross": "230.00", "payable": "230.00", "reporting": "230.00" }, "pendedAt": null, "cancelledAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invoices failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. - Money is sent as an exact decimal string. Entry prices are net of VAT; the workspace payable modifier supplies the tax value. --- # Upsert invoice **PUT** `/v1/invoices/{invoiceId}` Upsert an incoming service invoice with Client and Project context, authored net entries, and modifiers, preserving exact decimal values and the selected currency. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/upsert](https://docs.nqd.app/v1/reference/invoices/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | No | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `name` | `string` | No | Yes | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting services"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting service"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `pendedAt` | `string` | No | Yes | ISO 8601 timestamp for pended. | `"2026-01-15T12:00:00.000Z"` | | `cancelledAt` | `string` | No | Yes | ISO 8601 timestamp for cancelled. | `"2026-01-15T12:00:00.000Z"` | ```json { "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.shortId` | `string` | Yes | No | ID of the related short. | `"INV-0001"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data.projectWebsite` | `string` | No | Yes | project website for this invoice. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this invoice. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this invoice. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.contactWebsite` | `string[]` | No | Yes | contact website for this invoice. | `["https://example.com"]` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.invoiceRecurringId` | `string` | Yes | Yes | ID of the related invoice recurring. | `null` | | `data.recurringSourceName` | `string` | No | Yes | recurring source name for this invoice. | `"Consulting services"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"Consulting services"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.totals` | `object` | No | Yes | totals for this invoice. | — | | `data.totals.lineTotals` | `object` | No | Yes | line totals within totals. | — | | `data.totals.base` | `string` | No | Yes | base within totals. | `"200.00"` | | `data.totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"200.00"` | | `data.totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"30.00"` | | `data.totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"230.00"` | | `data.totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"230.00"` | | `data.totals.reporting` | `string` | No | Yes | Amount converted to the workspace reporting currency. | `"230.00"` | | `data.recurringOn` | `string` | No | Yes | recurring on for this invoice. | `"2026-01-15"` | | `data.settled` | `boolean` | No | Yes | Whether effective transactions cover the amount due. | `false` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this invoice. | `null` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data.cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "shortId": "INV-0001", "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "invoiceRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "200.00" }, "base": "200.00", "net": "200.00", "tax": "30.00", "gross": "230.00", "payable": "230.00", "reporting": "230.00" }, "pendedAt": null, "cancelledAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete invoice **DELETE** `/v1/invoices/{invoiceId}` Delete invoice. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/delete](https://docs.nqd.app/v1/reference/invoices/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Upsert invoices in a batch **PUT** `/v1/invoices` Upsert invoices atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/bulk-upsert](https://docs.nqd.app/v1/reference/invoices/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `clientId` | `string` | No | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `projectId` | `string` | No | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | No | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `name` | `string` | No | Yes | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting services"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Consulting service"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"inbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `pendedAt` | `string` | No | Yes | ISO 8601 timestamp for pended. | `"2026-01-15T12:00:00.000Z"` | | `cancelledAt` | `string` | No | Yes | ISO 8601 timestamp for cancelled. | `"2026-01-15T12:00:00.000Z"` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data[].shortId` | `string` | Yes | No | ID of the related short. | `"INV-0001"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this invoice. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this invoice. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this invoice. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this invoice. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].invoiceRecurringId` | `string` | Yes | Yes | ID of the related invoice recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this invoice. | `"Consulting services"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Consulting services"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Consulting service"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].totals` | `object` | No | Yes | totals for this invoice. | — | | `data[].totals.lineTotals` | `object` | No | Yes | line totals within totals. | — | | `data[].totals.base` | `string` | No | Yes | base within totals. | `"200.00"` | | `data[].totals.net` | `string` | Yes | No | Total before tax and other modifiers. | `"200.00"` | | `data[].totals.tax` | `string` | Yes | No | Tax calculated from the workspace payable modifier. | `"30.00"` | | `data[].totals.gross` | `string` | Yes | No | Total after tax and other price modifiers. | `"230.00"` | | `data[].totals.payable` | `string` | Yes | No | Amount due after all applied modifiers. | `"230.00"` | | `data[].totals.reporting` | `string` | No | Yes | Amount converted to the workspace reporting currency. | `"230.00"` | | `data[].recurringOn` | `string` | No | Yes | recurring on for this invoice. | `"2026-01-15"` | | `data[].settled` | `boolean` | No | Yes | Whether effective transactions cover the amount due. | `false` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this invoice. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data[].cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "shortId": "INV-0001", "clientId": null, "projectId": null, "contactId": null, "bankAccountId": null, "invoiceRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "name": "Consulting services", "description": "Consulting services for January 2026", "notes": "Consulting services", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "totals": { "lineTotals": { "01JQ2T5Y5Q3R8W9N6M4K2H7P1H": "200.00" }, "base": "200.00", "net": "200.00", "tax": "30.00", "gross": "230.00", "payable": "230.00", "reporting": "230.00" }, "pendedAt": null, "cancelledAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Consulting services", "description": "Consulting services for January 2026", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Consulting service", "description": "Monthly consulting service", "quantity": "2.00", "unit": "hour", "pricePerUnit": "100.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List applied entries for an invoice **GET** `/v1/invoices/{invoiceId}/entries` Return the complete applied collection snapshot for an invoice. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/entries/list](https://docs.nqd.app/v1/reference/invoices/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Add applied entry to an invoice **POST** `/v1/invoices/{invoiceId}/entries` Add applied entry to an invoice and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/entries/create](https://docs.nqd.app/v1/reference/invoices/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Consulting service", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Consulting service", "description": "Monthly consulting service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Consulting service", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Consulting service", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Partially update applied entry on an invoice **PATCH** `/v1/invoices/{invoiceId}/entries/{entryId}` Partially update applied entry on an invoice and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/entries/update](https://docs.nqd.app/v1/reference/invoices/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Consulting service" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Consulting service", "description": "Monthly consulting service", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Consulting service" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Consulting service" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied entry from an invoice **DELETE** `/v1/invoices/{invoiceId}/entries/{entryId}` Remove applied entry from an invoice and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/entries/delete](https://docs.nqd.app/v1/reference/invoices/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Reorder applied entries for an invoice **PUT** `/v1/invoices/{invoiceId}/entries/reorder` Replace the complete order of applied entries for an invoice and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/entries/reorder/upsert](https://docs.nqd.app/v1/reference/invoices/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # List applied modifiers for an invoice **GET** `/v1/invoices/{invoiceId}/modifiers` Return the complete applied collection snapshot for an invoice. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/modifiers/list](https://docs.nqd.app/v1/reference/invoices/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Add applied modifier to an invoice **POST** `/v1/invoices/{invoiceId}/modifiers` Add applied modifier to an invoice and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/modifiers/create](https://docs.nqd.app/v1/reference/invoices/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `kind` | `string` | No | Yes | kind for this invoice. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this invoice. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this invoice. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Partially update applied modifier on an invoice **PATCH** `/v1/invoices/{invoiceId}/modifiers/{modifierId}` Partially update applied modifier on an invoice and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/modifiers/update](https://docs.nqd.app/v1/reference/invoices/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `kind` | `string` | No | Yes | kind for this invoice. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this invoice. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this invoice. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied modifier from an invoice **DELETE** `/v1/invoices/{invoiceId}/modifiers/{modifierId}` Remove applied modifier from an invoice and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/modifiers/delete](https://docs.nqd.app/v1/reference/invoices/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # Reorder applied modifiers for an invoice **PUT** `/v1/invoices/{invoiceId}/modifiers/reorder` Replace the complete order of applied modifiers for an invoice and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/invoices/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `invoiceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1P" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Consulting service"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Monthly consulting service"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Consulting service", "description": "Monthly consulting service", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1P" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1P" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - An Invoice is an incoming service source. Use Client and Project for the service context and Entries for the priced units. It may be unpaid or partially paid; record cash separately through Transactions. --- # List transactions **GET** `/v1/invoices/{sourceId}/transactions` Retrieve matching transactions. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/transactions/list](https://docs.nqd.app/v1/reference/invoices/transactions/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter invoices by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[amount]` | `string` | No | No | Filter invoices by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[direction]` | `string` | No | No | Filter invoices by direction. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.inbound"` | | `filter[createdAt]` | `string` | No | No | Filter invoices by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[bankAccountId]` | `string` | No | No | Filter invoices by bankAccountId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[originalId]` | `string` | No | No | Filter invoices by originalId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceId]` | `string` | No | No | Filter invoices by sourceId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceType]` | `string` | No | No | Filter invoices by sourceType. Use operator.value syntax. (eq, neq, in operators) | `"eq.invoice"` | | `filter[currencyCode]` | `string` | No | No | Filter invoices by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,source"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,amount.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data[].source` | `object` | Yes | Yes | source for this invoice. | — | | `data[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].direction` | `string` | Yes | No | direction for this invoice. (Allowed values: "inbound", "outbound") | `"inbound"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].accountLabel` | `string` | No | Yes | account label for this invoice. | `"Consulting services"` | | `data[].originalId` | `string` | Yes | Yes | ID of the related original. | `"Consulting services"` | | `data[].context` | `object` | Yes | No | context for this invoice. | — | | `data[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "type": "invoice" }, "amount": "100.00", "direction": "inbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "bankAccountId": null, "originalId": "Consulting services", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # Record a payment **POST** `/v1/invoices/{sourceId}/transactions` Record a payment against the source using its currency and the selected or default bank account. - Canonical URL: [https://docs.nqd.app/v1/reference/invoices/transactions/create](https://docs.nqd.app/v1/reference/invoices/transactions/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque invoice resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this invoice. | `true` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": true } } ``` ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this invoice. | `false` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": false } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/invoices/01JQ2T5Y5Q3R8W9N6M4K2H7P1P/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. - The payment uses the source currency and the selected or configured workspace bank account; validate conversion when currencies differ. --- # List integration logs **GET** `/v1/logs` List integration activity records for the workspace with bounded filters and cursor pagination. - Canonical URL: [https://docs.nqd.app/v1/reference/logs/list](https://docs.nqd.app/v1/reference/logs/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter logs by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[action]` | `string` | No | No | Filter logs by action. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[operationId]` | `string` | No | No | Filter logs by operationId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[occurredAt]` | `string` | No | No | Filter logs by occurredAt. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,action"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,action.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 250) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 250. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Integration log value retained for delivery and debugging. | — | | `data[].id` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2A"` | | `data[].action` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Maximum length: 128 characters.) | `"Consulting services"` | | `data[].recordId` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data[].actorId` | `string` | Yes | Yes | Integration log value retained for delivery and debugging. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data[].operationId` | `string` | Yes | Yes | Integration log value retained for delivery and debugging. (Minimum length: 1 character., Maximum length: 128 characters.) | `"invoices.upsert"` | | `data[].occurredAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Integration log value retained for delivery and debugging. | `null` | | `page.total` | `number` | No | Yes | Integration log value retained for delivery and debugging. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P2A", "action": "Consulting services", "recordId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "actorId": null, "operationId": "invoices.upsert", "occurredAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Integration log value retained for delivery and debugging. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Integration log value retained for delivery and debugging. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Integration log value retained for delivery and debugging. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Integration log value retained for delivery and debugging. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/logs" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/logs", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/logs failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Use the returned nextCursor for the next page. Do not combine cursor with before, beforeId, or beforeAttempt. --- # List modifiers **GET** `/v1/modifiers` Retrieve matching modifiers. - Canonical URL: [https://docs.nqd.app/v1/reference/modifiers/list](https://docs.nqd.app/v1/reference/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter modifiers by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter modifiers by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter modifiers by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[value]` | `string` | No | No | Filter modifiers by value. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[archivedAt]` | `string` | No | No | Filter modifiers by archivedAt. Use operator.value syntax. (eq, neq, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter modifiers by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter modifiers by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[percentage]` | `string` | No | No | Filter modifiers by percentage. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in operators) | `"eq.100.00"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data[].currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve modifier **GET** `/v1/modifiers/{modifierId}` Return the addressed modifier. - Canonical URL: [https://docs.nqd.app/v1/reference/modifiers/retrieve](https://docs.nqd.app/v1/reference/modifiers/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `modifierId` | `string` | Yes | No | An opaque modifier resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create modifiers **POST** `/v1/modifiers` Create modifiers from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/modifiers/create](https://docs.nqd.app/v1/reference/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data[].currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert modifier **PUT** `/v1/modifiers/{modifierId}` Create or update the addressed modifier. - Canonical URL: [https://docs.nqd.app/v1/reference/modifiers/upsert](https://docs.nqd.app/v1/reference/modifiers/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `modifierId` | `string` | Yes | No | An opaque modifier resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | ```json { "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Archive modifier **DELETE** `/v1/modifiers/{modifierId}` Archive modifier. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/modifiers/delete](https://docs.nqd.app/v1/reference/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `modifierId` | `string` | Yes | No | An opaque modifier resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1J failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert modifiers in a batch **PUT** `/v1/modifiers` Upsert modifiers atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/modifiers/bulk-upsert](https://docs.nqd.app/v1/reference/modifiers/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null, "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data[].currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].archivedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was archived, or null when it is active. | `null` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "archivedAt": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null, "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "value": "5", "currencyId": null, "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Set the workspace tax modifier **PUT** `/v1/modifiers/tax` Set the workspace tax modifier. - Canonical URL: [https://docs.nqd.app/v1/reference/modifiers/set-tax](https://docs.nqd.app/v1/reference/modifiers/set-tax) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `id` | `string` | Yes | Yes | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | ```json { "id": null } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.taxModifierId` | `string` | Yes | Yes | Identifier of the workspace payable modifier used to calculate VAT. Apply the matching modifier in the flat modifiers array. | `"100.00"` | ```json { "data": { "taxModifierId": "100.00" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/modifiers/tax" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "id": null }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/modifiers/tax", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "id": null }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/modifiers/tax failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List workspace participants **GET** `/v1/participants` Retrieve matching workspace participants. - Canonical URL: [https://docs.nqd.app/v1/reference/participants/list](https://docs.nqd.app/v1/reference/participants/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[profileId]` | `string` | No | No | Filter participants by profileId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `filter[username]` | `string` | No | No | Filter participants by username. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[email]` | `string` | No | No | Filter participants by email. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[role]` | `string` | No | No | Filter participants by role. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.owner"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"profileId,username"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"profileId.asc,username.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].profileId` | `string` | Yes | No | ID of the related profile. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].username` | `string` | Yes | No | username for this participant. | `"owner"` | | `data[].email` | `string` | Yes | No | Email address associated with the identity. | `"owner@example.com"` | | `data[].role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "username": "owner", "email": "owner@example.com", "role": "owner" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/participants" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/participants", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/participants failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Delete workspace participant **DELETE** `/v1/participants/{profileId}` Delete workspace participant. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/participants/delete](https://docs.nqd.app/v1/reference/participants/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `profileId` | `string` | Yes | No | An opaque profile resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/participants/01JQ2T5Y5Q3R8W9N6M4K2H7P1B" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/participants/01JQ2T5Y5Q3R8W9N6M4K2H7P1B", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/participants/01JQ2T5Y5Q3R8W9N6M4K2H7P1B failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Update a workspace participant role **PUT** `/v1/participants/{profileId}/role` Update the participant role. - Canonical URL: [https://docs.nqd.app/v1/reference/participants/role/upsert](https://docs.nqd.app/v1/reference/participants/role/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `profileId` | `string` | Yes | No | An opaque profile resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | ```json { "role": "owner" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.member` | `object` | Yes | Yes | member for this participant. | — | | `data.member.profileId` | `string` | Yes | No | ID of the related profile. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.member.username` | `string` | Yes | No | username within member. | `"owner"` | | `data.member.email` | `string` | Yes | No | Email address associated with the identity. | `"owner@example.com"` | | `data.member.role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | ```json { "data": { "member": { "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "username": "owner", "email": "owner@example.com", "role": "owner" } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/participants/01JQ2T5Y5Q3R8W9N6M4K2H7P1B/role" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "role": "owner" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/participants/01JQ2T5Y5Q3R8W9N6M4K2H7P1B/role", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "role": "owner" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/participants/01JQ2T5Y5Q3R8W9N6M4K2H7P1B/role failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read payable settings **GET** `/v1/settings/payables` Retrieve matching payable settings. - Canonical URL: [https://docs.nqd.app/v1/reference/settings/payables/list](https://docs.nqd.app/v1/reference/settings/payables/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter payables by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[vendorId]` | `string` | No | No | Filter payables by vendorId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[modifierId]` | `string` | No | No | Filter payables by modifierId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `filter[purpose]` | `string` | No | No | Filter payables by purpose. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,vendorId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,vendorId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].modifierId` | `string` | Yes | No | ID of the related modifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].purpose` | `string` | Yes | Yes | purpose for this payable. | `"Consulting services"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "Consulting services", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "purpose": "Consulting services" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/settings/payables" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/settings/payables", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/settings/payables failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Save payable settings **PUT** `/v1/settings/payables` Save payable settings. - Canonical URL: [https://docs.nqd.app/v1/reference/settings/payables/upsert](https://docs.nqd.app/v1/reference/settings/payables/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `operation` | `string` | Yes | No | operation for this payable. (Allowed values: "create", "update", "delete") | `"create"` | | `vendorId` | `string` | Yes | No | ID of the related vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `modifierId` | `string` | No | Yes | ID of the related modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `originalVendorId` | `string` | No | Yes | ID of the related original vendor. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `purpose` | `string` | No | Yes | purpose for this payable. (Allowed values: "custom", "vat", "zakah") | `"custom"` | | `originalPurpose` | `string` | No | Yes | original purpose for this payable. (Allowed values: "custom", "vat", "zakah") | `"custom"` | ```json { "operation": "create", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.modifierId` | `string` | Yes | No | ID of the related modifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.purpose` | `string` | Yes | Yes | purpose for this payable. | `"Consulting services"` | ```json { "data": { "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "purpose": "Consulting services" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/settings/payables" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "operation": "create", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/settings/payables", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "operation": "create", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/settings/payables failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List payout templates **GET** `/v1/payouts/templates` Retrieve matching payout templates. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/list](https://docs.nqd.app/v1/reference/payouts/templates/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter payout-templates by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[projectId]` | `string` | No | No | Filter payout-templates by projectId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `filter[contactId]` | `string` | No | No | Filter payout-templates by contactId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `filter[bankAccountId]` | `string` | No | No | Filter payout-templates by bankAccountId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[tags]` | `string` | No | No | Filter payout-templates by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[recurrenceMonths]` | `string` | No | No | Filter payout-templates by recurrenceMonths. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in operators) | `"eq.1"` | | `filter[amount]` | `string` | No | No | Filter payout-templates by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[startedAt]` | `string` | No | No | Filter payout-templates by startedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[endedAt]` | `string` | No | No | Filter payout-templates by endedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[nextDueAt]` | `string` | No | No | Filter payout-templates by nextDueAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter payout-templates by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdBy]` | `string` | No | No | Filter payout-templates by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedAt]` | `string` | No | No | Filter payout-templates by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedBy]` | `string` | No | No | Filter payout-templates by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[deletedAt]` | `string` | No | No | Filter payout-templates by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedBy]` | `string` | No | No | Filter payout-templates by deletedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[currencyId]` | `string` | No | No | Filter payout-templates by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter payout-templates by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,projectId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,projectId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `data[].projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this payout template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this payout template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this payout template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this payout template. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this payout template. | `1` | | `data[].amount` | `string` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this payout template. | `null` | | `data[].startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1V", "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "recurrenceMonths": 1, "amount": "100.00", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Create payout templates **POST** `/v1/payouts/templates` Create payout templates from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/create](https://docs.nqd.app/v1/reference/payouts/templates/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `projectId` | `string` | Yes | No | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this payout template. (maximum 1200, greater than 0) | `1` | | `startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `data[].projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this payout template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this payout template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this payout template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this payout template. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this payout template. | `1` | | `data[].amount` | `string` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this payout template. | `null` | | `data[].startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1V", "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "recurrenceMonths": 1, "amount": "100.00", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/payouts/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Upsert payout template **PUT** `/v1/payouts/templates/{templateId}` Create or update the addressed payout template. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/upsert](https://docs.nqd.app/v1/reference/payouts/templates/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `projectId` | `string` | Yes | No | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this payout template. (maximum 1200, greater than 0) | `1` | | `startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | ```json { "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `data.projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data.projectWebsite` | `string` | No | Yes | project website for this payout template. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this payout template. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this payout template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.contactWebsite` | `string[]` | No | Yes | contact website for this payout template. | `["https://example.com"]` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.recurrenceMonths` | `number` | Yes | No | recurrence months for this payout template. | `1` | | `data.amount` | `string` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this payout template. | `null` | | `data.startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data.endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data.nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1V", "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "recurrenceMonths": 1, "amount": "100.00", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Delete payout template **DELETE** `/v1/payouts/templates/{templateId}` Delete payout template. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/delete](https://docs.nqd.app/v1/reference/payouts/templates/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Upsert payout templates in a batch **PUT** `/v1/payouts/templates` Upsert payout templates atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/bulk-upsert](https://docs.nqd.app/v1/reference/payouts/templates/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `projectId` | `string` | Yes | No | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `recurrenceMonths` | `number` | Yes | No | recurrence months for this payout template. (maximum 1200, greater than 0) | `1` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1V", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `data[].projectId` | `string` | Yes | No | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this payout template. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this payout template. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this payout template. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this payout template. | `["https://example.com"]` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].recurrenceMonths` | `number` | Yes | No | recurrence months for this payout template. | `1` | | `data[].amount` | `string` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this payout template. | `null` | | `data[].startedAt` | `string` | Yes | No | ISO 8601 timestamp for started. | `"2026-01-15T12:00:00.000Z"` | | `data[].endedAt` | `string` | Yes | Yes | ISO 8601 timestamp for ended. | `"2026-01-15T12:00:00.000Z"` | | `data[].nextDueAt` | `string` | Yes | Yes | ISO 8601 timestamp for next due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1V", "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "recurrenceMonths": 1, "amount": "100.00", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z", "nextDueAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1V", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "projectId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "recurrenceMonths": 1, "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1V", "startedAt": "2026-01-15T12:00:00.000Z", "endedAt": "2026-01-15T12:00:00.000Z" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts/templates failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # List applied entries for a payout template **GET** `/v1/payouts/templates/{templateId}/entries` Return the complete applied collection snapshot for a payout template. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/entries/list](https://docs.nqd.app/v1/reference/payouts/templates/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Add applied entry to a payout template **POST** `/v1/payouts/templates/{templateId}/entries` Add applied entry to a payout template and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/entries/create](https://docs.nqd.app/v1/reference/payouts/templates/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Contractor payment", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Contractor payment", "description": "Contractor payment for January 2026", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Contractor payment", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Contractor payment", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Partially update applied entry on a payout template **PATCH** `/v1/payouts/templates/{templateId}/entries/{entryId}` Partially update applied entry on a payout template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/entries/update](https://docs.nqd.app/v1/reference/payouts/templates/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Contractor payment" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Contractor payment", "description": "Contractor payment for January 2026", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Contractor payment" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Contractor payment" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Remove applied entry from a payout template **DELETE** `/v1/payouts/templates/{templateId}/entries/{entryId}` Remove applied entry from a payout template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/entries/delete](https://docs.nqd.app/v1/reference/payouts/templates/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Reorder applied entries for a payout template **PUT** `/v1/payouts/templates/{templateId}/entries/reorder` Replace the complete order of applied entries for a payout template and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/entries/reorder/upsert](https://docs.nqd.app/v1/reference/payouts/templates/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # List applied modifiers for a payout template **GET** `/v1/payouts/templates/{templateId}/modifiers` Return the complete applied collection snapshot for a payout template. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/modifiers/list](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Add applied modifier to a payout template **POST** `/v1/payouts/templates/{templateId}/modifiers` Add applied modifier to a payout template and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/modifiers/create](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `kind` | `string` | No | Yes | kind for this payout template. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this payout template. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this payout template. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Partially update applied modifier on a payout template **PATCH** `/v1/payouts/templates/{templateId}/modifiers/{modifierId}` Partially update applied modifier on a payout template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/modifiers/update](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `kind` | `string` | No | Yes | kind for this payout template. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this payout template. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this payout template. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Recurring templates store schedules. The recurring process creates due records and payments. --- # Remove applied modifier from a payout template **DELETE** `/v1/payouts/templates/{templateId}/modifiers/{modifierId}` Remove applied modifier from a payout template and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/modifiers/delete](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # Reorder applied modifiers for a payout template **PUT** `/v1/payouts/templates/{templateId}/modifiers/reorder` Replace the complete order of applied modifiers for a payout template and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/templates/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/payouts/templates/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `templateId` | `string` | Yes | No | An opaque payout_recurring resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1V"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1V" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1V" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1V" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts/templates/01JQ2T5Y5Q3R8W9N6M4K2H7P1V/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Recurring templates store schedules. The recurring process creates due records and payments. --- # List payouts **GET** `/v1/payouts` Retrieve matching payouts. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/list](https://docs.nqd.app/v1/reference/payouts/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter payouts by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter payouts by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter payouts by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[projectId]` | `string` | No | No | Filter payouts by projectId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `filter[clientId]` | `string` | No | No | Filter payouts by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[invoiceId]` | `string` | No | No | Filter payouts by invoiceId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `filter[contactId]` | `string` | No | No | Filter payouts by contactId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | | `filter[bankAccountId]` | `string` | No | No | Filter payouts by bankAccountId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[payoutRecurringId]` | `string` | No | No | Filter payouts by payoutRecurringId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[amount]` | `string` | No | No | Filter payouts by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[tags]` | `string` | No | No | Filter payouts by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[status]` | `string` | No | No | Filter payouts by status. Use operator.value syntax. (eq, neq, in operators) | `"eq.draft"` | | `filter[createdAt]` | `string` | No | No | Filter payouts by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdBy]` | `string` | No | No | Filter payouts by createdBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[updatedAt]` | `string` | No | No | Filter payouts by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedBy]` | `string` | No | No | Filter payouts by updatedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[deletedAt]` | `string` | No | No | Filter payouts by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedBy]` | `string` | No | No | Filter payouts by deletedBy. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[pendedAt]` | `string` | No | No | Filter payouts by pendedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[cancelledAt]` | `string` | No | No | Filter payouts by cancelledAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[currencyId]` | `string` | No | No | Filter payouts by currencyId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `filter[currencyCode]` | `string` | No | No | Filter payouts by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `filter[activityAt]` | `string` | No | No | Filter payouts by activityAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Contractor payment"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Contractor payment for January 2026"` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this payout. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this payout. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this payout. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this payout. | `["https://example.com"]` | | `data[].invoiceId` | `string` | Yes | Yes | ID of the related invoice. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].payoutRecurringId` | `string` | Yes | Yes | ID of the related payout recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this payout. | `"Consulting services"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "draft", "pending", "paid", "overpaid", "cancelled") | `"draft"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this payout. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `data[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data[].cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "name": "Contractor payment", "description": "Contractor payment for January 2026", "projectId": null, "clientId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "payoutRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "amount": "100.00", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "status": "draft", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null, "pendedAt": null, "cancelledAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Retrieve payout **GET** `/v1/payouts/{payoutId}` Return the addressed payout. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/retrieve](https://docs.nqd.app/v1/reference/payouts/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"Contractor payment"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Contractor payment for January 2026"` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectWebsite` | `string` | No | Yes | project website for this payout. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this payout. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this payout. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.contactWebsite` | `string[]` | No | Yes | contact website for this payout. | `["https://example.com"]` | | `data.invoiceId` | `string` | Yes | Yes | ID of the related invoice. | `null` | | `data.contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.payoutRecurringId` | `string` | Yes | Yes | ID of the related payout recurring. | `null` | | `data.recurringSourceName` | `string` | No | Yes | recurring source name for this payout. | `"Consulting services"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "draft", "pending", "paid", "overpaid", "cancelled") | `"draft"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this payout. | `null` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `data.pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data.cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "name": "Contractor payment", "description": "Contractor payment for January 2026", "projectId": null, "clientId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "payoutRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "amount": "100.00", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "status": "draft", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null, "pendedAt": null, "cancelledAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Create payouts **POST** `/v1/payouts` Create outgoing payment payouts for an individual Contact service from authored net entries and modifiers. Preserve exact decimal values and the selected currency. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/create](https://docs.nqd.app/v1/reference/payouts/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `invoiceId` | `string` | Yes | Yes | ID of the related invoice. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `payoutRecurringId` | `string` | No | Yes | ID of the related payout recurring. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"outbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | ```json [ { "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "pendedAt": null, "cancelledAt": null } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Contractor payment"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Contractor payment for January 2026"` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this payout. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this payout. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this payout. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this payout. | `["https://example.com"]` | | `data[].invoiceId` | `string` | Yes | Yes | ID of the related invoice. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].payoutRecurringId` | `string` | Yes | Yes | ID of the related payout recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this payout. | `"Consulting services"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "draft", "pending", "paid", "overpaid", "cancelled") | `"draft"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this payout. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `data[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data[].cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "name": "Contractor payment", "description": "Contractor payment for January 2026", "projectId": null, "clientId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "payoutRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "amount": "100.00", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "status": "draft", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null, "pendedAt": null, "cancelledAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "pendedAt": null, "cancelledAt": null } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "pendedAt": null, "cancelledAt": null } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/payouts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. - Money is sent as an exact decimal string. Entry prices are net of VAT; the workspace payable modifier supplies the tax value. --- # Upsert payout **PUT** `/v1/payouts/{payoutId}` Upsert an outgoing individual-Contact-service payout with authored net entries and modifiers, preserving exact decimal values and the selected currency. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/upsert](https://docs.nqd.app/v1/reference/payouts/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | No | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `invoiceId` | `string` | Yes | Yes | ID of the related invoice. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `payoutRecurringId` | `string` | No | Yes | ID of the related payout recurring. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"outbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | ```json { "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "pendedAt": null, "cancelledAt": null } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"Contractor payment"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Contractor payment for January 2026"` | | `data.projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.projectWebsite` | `string` | No | Yes | project website for this payout. | `"https://example.com"` | | `data.clientWebsite` | `string[]` | No | Yes | client website for this payout. | `["Consulting services"]` | | `data.clientType` | `string` | No | Yes | client type for this payout. (Allowed values: "individual", "company", "government") | `"individual"` | | `data.contactWebsite` | `string[]` | No | Yes | contact website for this payout. | `["https://example.com"]` | | `data.invoiceId` | `string` | Yes | Yes | ID of the related invoice. | `null` | | `data.contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data.bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data.payoutRecurringId` | `string` | Yes | Yes | ID of the related payout recurring. | `null` | | `data.recurringSourceName` | `string` | No | Yes | recurring source name for this payout. | `"Consulting services"` | | `data.currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "draft", "pending", "paid", "overpaid", "cancelled") | `"draft"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this payout. | `null` | | `data.settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `data.pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data.cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "name": "Contractor payment", "description": "Contractor payment for January 2026", "projectId": null, "clientId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "payoutRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "amount": "100.00", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "status": "draft", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null, "pendedAt": null, "cancelledAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "pendedAt": null, "cancelledAt": null }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), ...(env.NQD_IF_MATCH ? { "If-Match": env.NQD_IF_MATCH } : {}), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "pendedAt": null, "cancelledAt": null }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete payout **DELETE** `/v1/payouts/{payoutId}` Delete payout. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/delete](https://docs.nqd.app/v1/reference/payouts/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Upsert payouts in a batch **PUT** `/v1/payouts` Upsert payouts atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/bulk-upsert](https://docs.nqd.app/v1/reference/payouts/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `projectId` | `string` | Yes | Yes | Project identifier within the current workspace. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `invoiceId` | `string` | Yes | Yes | ID of the related invoice. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `payoutRecurringId` | `string` | No | Yes | ID of the related payout recurring. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1V"` | | `bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `entries[].name` | `string` | Yes | No | Display name of the resource. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `entries[].description` | `string` | Yes | No | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `modifiers[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `modifiers[].description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Value added tax"` | | `modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `paymentPlan` | `object[]` | No | Yes | Payment schedule for the record. (at most 500 items) | — | | `paymentPlan[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `paymentPlan[].originalId` | `string` | No | Yes | ID of the related original. | `"Consulting services"` | | `paymentPlan[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `paymentPlan[].amountMode` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Allowed values: "replace") | `"replace"` | | `paymentPlan[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `paymentPlan[].direction` | `string` | Yes | No | direction within payment plan. (Allowed values: "inbound", "outbound") | `"outbound"` | | `paymentPlan[].bankAccountId` | `string` | Yes | No | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `paymentPlan[].createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `expectedUpdatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json [ { "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "pendedAt": null, "cancelledAt": null } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"Contractor payment"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Contractor payment for January 2026"` | | `data[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].projectWebsite` | `string` | No | Yes | project website for this payout. | `"https://example.com"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this payout. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this payout. (Allowed values: "individual", "company", "government") | `"individual"` | | `data[].contactWebsite` | `string[]` | No | Yes | contact website for this payout. | `["https://example.com"]` | | `data[].invoiceId` | `string` | Yes | Yes | ID of the related invoice. | `null` | | `data[].contactId` | `string` | Yes | Yes | Contact identifier for the payout recipient. It is independent of the project client. | `null` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].payoutRecurringId` | `string` | Yes | Yes | ID of the related payout recurring. | `null` | | `data[].recurringSourceName` | `string` | No | Yes | recurring source name for this payout. | `"Consulting services"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. (at least 1 items, at most 1000 items) | — | | `data[].entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data[].entries[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].entries[].name` | `string` | Yes | No | Display name of the record. (Maximum length: 10000 characters.) | `"Contractor payment"` | | `data[].entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data[].entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data[].entries[].unit` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data[].entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data[].modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. (at most 1000 items) | — | | `data[].modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data[].modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data[].modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data[].modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data[].modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "draft", "pending", "paid", "overpaid", "cancelled") | `"draft"` | | `data[].createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data[].updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data[].deletedBy` | `string` | Yes | Yes | deleted by for this payout. | `null` | | `data[].settledAt` | `string` | No | Yes | Timestamp when effective transactions covered the amount due. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `data[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data[].cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "name": "Contractor payment", "description": "Contractor payment for January 2026", "projectId": null, "clientId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "payoutRecurringId": null, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "amount": "100.00", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%" } ], "tags": [ "equipment" ], "status": "draft", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null, "pendedAt": null, "cancelledAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "pendedAt": null, "cancelledAt": null } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "Contractor payment", "description": "Contractor payment for January 2026", "clientId": null, "projectId": null, "invoiceId": null, "contactId": null, "bankAccountId": null, "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "Contractor payment", "description": "Contractor payment for January 2026", "quantity": "2.00", "unit": "hour", "pricePerUnit": "500.00" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "description": "Value added tax", "value": "15.00%" } ], "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "pendedAt": null, "cancelledAt": null } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List applied entries for a payout **GET** `/v1/payouts/{payoutId}/entries` Return the complete applied collection snapshot for a payout. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/entries/list](https://docs.nqd.app/v1/reference/payouts/entries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Add applied entry to a payout **POST** `/v1/payouts/{payoutId}/entries` Add applied entry to a payout and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/entries/create](https://docs.nqd.app/v1/reference/payouts/entries/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogEntryId` | `string` | No | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"unspecified"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Contractor payment", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Contractor payment", "description": "Contractor payment for January 2026", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Contractor payment", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Contractor payment", "unitCode": "unspecified", "quantity": "2.00", "pricePerUnit": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Partially update applied entry on a payout **PATCH** `/v1/payouts/{payoutId}/entries/{entryId}` Partially update applied entry on a payout and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/entries/update](https://docs.nqd.app/v1/reference/payouts/entries/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `unitCode` | `string` | No | Yes | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `quantity` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `pricePerUnit` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | ```json { "name": "Contractor payment" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Contractor payment", "description": "Contractor payment for January 2026", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Contractor payment" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Contractor payment" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied entry from a payout **DELETE** `/v1/payouts/{payoutId}/entries/{entryId}` Remove applied entry from a payout and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/entries/delete](https://docs.nqd.app/v1/reference/payouts/entries/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `entryId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Reorder applied entries for a payout **PUT** `/v1/payouts/{payoutId}/entries/reorder` Replace the complete order of applied entries for a payout and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/entries/reorder/upsert](https://docs.nqd.app/v1/reference/payouts/entries/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1H"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1H" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/entries/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # List applied modifiers for a payout **GET** `/v1/payouts/{payoutId}/modifiers` Return the complete applied collection snapshot for a payout. Applied values are independent saved facts; catalog entry or modifier provenance is optional and never rewrites the snapshot. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/modifiers/list](https://docs.nqd.app/v1/reference/payouts/modifiers/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Add applied modifier to a payout **POST** `/v1/payouts/{payoutId}/modifiers` Add applied modifier to a payout and return the complete applied collection snapshot. Catalog provenance may be supplied, or authored fields may be used directly; the public applied ID is stable and separate from catalog identity. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/modifiers/create](https://docs.nqd.app/v1/reference/payouts/modifiers/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `catalogModifierId` | `string` | No | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `kind` | `string` | No | Yes | kind for this payout. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this payout. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this payout. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Partially update applied modifier on a payout **PATCH** `/v1/payouts/{payoutId}/modifiers/{modifierId}` Partially update applied modifier on a payout and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; catalog provenance and saved applied facts remain separate. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/modifiers/update](https://docs.nqd.app/v1/reference/payouts/modifiers/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `kind` | `string` | No | Yes | kind for this payout. (Allowed values: "percentage", "fixed") | `"percentage"` | | `stage` | `string` | No | Yes | stage for this payout. (Allowed values: "price", "tax", "settlement") | `"price"` | | `effect` | `string` | No | Yes | effect for this payout. (Allowed values: "increase", "decrease") | `"increase"` | | `value` | `string` | No | Yes | Value returned by the operation. (Maximum length: 128 characters.) | `"5"` | | `entryId` | `string` | No | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | ```json { "name": "Service fee", "value": "5" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "name": "Service fee", "value": "5" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Service fee", "value": "5" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Remove applied modifier from a payout **DELETE** `/v1/payouts/{payoutId}/modifiers/{modifierId}` Remove applied modifier from a payout and return the complete applied collection snapshot. Send the latest updatedAt in If-Match; any modifier bound to a removed entry is cleaned up with that entry. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/modifiers/delete](https://docs.nqd.app/v1/reference/payouts/modifiers/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `modifierId` | `string` | Yes | No | An opaque id resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/01JQ2T5Y5Q3R8W9N6M4K2H7P1A failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # Reorder applied modifiers for a payout **PUT** `/v1/payouts/{payoutId}/modifiers/reorder` Replace the complete order of applied modifiers for a payout and return the complete applied collection snapshot. Send every applied ID exactly once in the desired order and the latest updatedAt in If-Match. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/modifiers/reorder/upsert](https://docs.nqd.app/v1/reference/payouts/modifiers/reorder/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `if-match` | `string` | Yes | No | Quoted updatedAt timestamp used to reject stale writes. Send the latest value as If-Match: "". (Minimum length: 3 characters., pattern ^".+"$) | `"\\"2026-01-15T12:00:00.000Z\\""` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `payoutId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `ids` | `string[]` | Yes | No | Complete ordered list of public applied IDs. Reorder requests must include every child ID exactly once. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ```json { "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1T" ] } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.entries` | `object[]` | Yes | No | Applied economic entries. Each entry is a reusable priced unit for a product, service, plan, or other calculable line. Entry prices are authored net prices; the workspace tax modifier calculates VAT. | — | | `data.entries[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.entries[].catalogEntryId` | `string` | Yes | Yes | Optional catalog entry reference used to seed this applied entry; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.entries[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Contractor payment"` | | `data.entries[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Contractor payment for January 2026"` | | `data.entries[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `data.entries[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.entries[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"500.00"` | | `data.entries[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].catalogModifierId` | `string` | Yes | Yes | Optional catalog modifier reference used to seed this applied modifier; catalog identity is separate from the saved applied fact. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].entryId` | `string` | Yes | Yes | Public applied entry ID that binds this modifier to an entry in the same applied snapshot. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"Service fee"` | | `data.modifiers[].description` | `string` | Yes | No | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].kind` | `string` | Yes | No | kind within modifiers. (Allowed values: "percentage", "fixed") | `"percentage"` | | `data.modifiers[].stage` | `string` | Yes | No | stage within modifiers. (Allowed values: "price", "tax", "settlement") | `"price"` | | `data.modifiers[].effect` | `string` | Yes | No | effect within modifiers. (Allowed values: "increase", "decrease") | `"increase"` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"5"` | | `data.modifiers[].currencyId` | `string` | Yes | Yes | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.updatedAt` | `string` | Yes | No | Applied snapshot revision. Send the latest value in If-Match for child writes; the response returns the new revision. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "entries": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "catalogEntryId": "Consulting services", "name": "Contractor payment", "description": "Contractor payment for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "500.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "catalogModifierId": "Consulting services", "entryId": null, "name": "Service fee", "description": "Value added tax", "kind": "percentage", "stage": "price", "effect": "increase", "value": "5", "currencyId": null } ], "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/reorder" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "If-Match: $NQD_IF_MATCH" \ -H "Content-Type: application/json" \ --data '{ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1T" ] }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/reorder", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "If-Match": requiredEnv("NQD_IF_MATCH"), "Content-Type": "application/json", }, body: JSON.stringify({ "ids": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1T" ] }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/modifiers/reorder failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - A Payout is an outgoing payment source for an individual Contact's service. Client, Project, and a customer Invoice are optional; a null Client means the current Workspace. If one person is both a Vendor and a Contact, the selected payee role determines Expense versus Payout. Record cash separately through Transactions. --- # List transactions **GET** `/v1/payouts/{sourceId}/transactions` Retrieve matching transactions. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/transactions/list](https://docs.nqd.app/v1/reference/payouts/transactions/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter payouts by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[amount]` | `string` | No | No | Filter payouts by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[direction]` | `string` | No | No | Filter payouts by direction. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.inbound"` | | `filter[createdAt]` | `string` | No | No | Filter payouts by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[bankAccountId]` | `string` | No | No | Filter payouts by bankAccountId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[originalId]` | `string` | No | No | Filter payouts by originalId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceId]` | `string` | No | No | Filter payouts by sourceId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceType]` | `string` | No | No | Filter payouts by sourceType. Use operator.value syntax. (eq, neq, in operators) | `"eq.invoice"` | | `filter[currencyCode]` | `string` | No | No | Filter payouts by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,source"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,amount.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data[].source` | `object` | Yes | Yes | source for this payout. | — | | `data[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].direction` | `string` | Yes | No | direction for this payout. (Allowed values: "inbound", "outbound") | `"outbound"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].accountLabel` | `string` | No | Yes | account label for this payout. | `"Consulting services"` | | `data[].originalId` | `string` | Yes | Yes | ID of the related original. | `"Consulting services"` | | `data[].context` | `object` | Yes | No | context for this payout. | — | | `data[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "type": "invoice" }, "amount": "100.00", "direction": "outbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "bankAccountId": null, "originalId": "Consulting services", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # Record a payment **POST** `/v1/payouts/{sourceId}/transactions` Record a payment against the source using its currency and the selected or default bank account. - Canonical URL: [https://docs.nqd.app/v1/reference/payouts/transactions/create](https://docs.nqd.app/v1/reference/payouts/transactions/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `sourceId` | `string` | Yes | No | An opaque payout resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `signedAmount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `bankAccountId` | `string` | No | Yes | ID of the related bank account. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this payout. | `true` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": true } } ``` ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this payout. | `false` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": false } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 422 — Request failed Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request failed."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "The request failed.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "signedAmount": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/payouts/01JQ2T5Y5Q3R8W9N6M4K2H7P1T/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. - The payment uses the source currency and the selected or configured workspace bank account; validate conversion when currencies differ. --- # List available billing plans **GET** `/v1/plans` Return available billing plans. - Canonical URL: [https://docs.nqd.app/v1/reference/plans/list](https://docs.nqd.app/v1/reference/plans/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter plans by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[kind]` | `string` | No | No | Filter plans by kind. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.free"` | | `filter[tier]` | `string` | No | No | Filter plans by tier. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.free"` | | `filter[monthlyPrice]` | `string` | No | No | Filter plans by monthlyPrice. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.1"` | | `filter[yearlyPrice]` | `string` | No | No | Filter plans by yearlyPrice. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.1"` | | `filter[currency]` | `string` | No | No | Filter plans by currency. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,kind"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,kind.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data[].kind` | `string` | Yes | No | kind for this plan. (Allowed values: "free", "pro", "business", "enterprise", "elite", "vip") | `"free"` | | `data[].tier` | `string` | Yes | No | tier for this plan. (Allowed values: "free", "solo", "team", "business", "enterprise") | `"free"` | | `data[].name` | `object` | Yes | No | Display name of the record. | — | | `data[].name.en` | `string` | Yes | No | en within name. | `"Consulting services"` | | `data[].name.ar` | `string` | Yes | No | ar within name. | `"Consulting services"` | | `data[].monthlyPrice` | `number` | Yes | No | monthly price for this plan. | `100` | | `data[].yearlyPrice` | `number` | Yes | No | yearly price for this plan. | `100` | | `data[].currency` | `string` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | `"Consulting services"` | | `data[].features` | `object` | Yes | No | features for this plan. | — | | `data[].features.recurringAutomation` | `boolean` | Yes | No | recurring automation within features. | `true` | | `data[].features.teamCollaboration` | `boolean` | Yes | No | team collaboration within features. | `true` | | `data[].features.webhooks` | `boolean` | Yes | No | webhooks within features. | `true` | | `data[].entitlements` | `object` | Yes | No | entitlements for this plan. | — | | `data[].entitlements.paymentsPerMonth` | `number` | Yes | No | payments per month within entitlements. | `100` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "Consulting services", "kind": "free", "tier": "free", "name": { "en": "Consulting services", "ar": "Consulting services" }, "monthlyPrice": 100, "yearlyPrice": 100, "currency": "Consulting services", "features": { "recurringAutomation": true, "teamCollaboration": true, "webhooks": true }, "entitlements": { "paymentsPerMonth": 100 } } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/plans" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/plans", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/plans failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Save workspace preferences **PUT** `/v1/preferences` Save preferences for the selected workspace. - Canonical URL: [https://docs.nqd.app/v1/reference/preferences/upsert](https://docs.nqd.app/v1/reference/preferences/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `profileId` | `string` | Yes | No | ID of the related profile. (Maximum length: 2048 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `scope` | `string` | Yes | No | scope for this preference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `revision` | `number` | Yes | No | revision for this preference. (minimum 0) | `100` | | `patch` | `object` | Yes | No | patch for this preference. | — | ```json { "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "scope": "Consulting services", "revision": 100, "patch": {} } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.conflict` | `boolean` | Yes | No | conflict for this preference. | `true` | | `data.record` | `object` | Yes | No | record for this preference. | — | | `data.record.scope` | `string` | Yes | No | scope within record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.record.preferences` | `object` | Yes | No | preferences within record. | — | | `data.record.schemaVersion` | `number` | Yes | No | schema version within record. | `100` | | `data.record.revision` | `number` | Yes | No | revision within record. | `100` | | `data.record.updatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "conflict": true, "record": { "scope": "Consulting services", "preferences": {}, "schemaVersion": 100, "revision": 100 } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/preferences" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "scope": "Consulting services", "revision": 100, "patch": {} }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/preferences", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "scope": "Consulting services", "revision": 100, "patch": {} }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/preferences failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read profile settings **GET** `/v1/profile` Read your profile. - Canonical URL: [https://docs.nqd.app/v1/reference/profile/retrieve](https://docs.nqd.app/v1/reference/profile/retrieve) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.username` | `string` | Yes | No | username for this profile. | `"owner"` | | `data.email` | `string` | Yes | No | Email address associated with the identity. | `"owner@example.com"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "username": "owner", "email": "owner@example.com" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/profile" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/profile", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/profile failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create the initial profile **POST** `/v1/profile` Create your profile. - Canonical URL: [https://docs.nqd.app/v1/reference/profile/create](https://docs.nqd.app/v1/reference/profile/create) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `username` | `string` | Yes | No | username for this profile. (Minimum length: 1 character., Maximum length: 32 characters.) | `"owner"` | ```json { "username": "owner" } ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.profileId` | `string` | Yes | No | ID of the related profile. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | ```json { "data": { "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/profile" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "username": "owner" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/profile", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, "Content-Type": "application/json", }, body: JSON.stringify({ "username": "owner" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/profile failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Update profile settings **PUT** `/v1/profile` Update your profile. - Canonical URL: [https://docs.nqd.app/v1/reference/profile/upsert](https://docs.nqd.app/v1/reference/profile/upsert) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `field` | `string` | Yes | No | field for this profile. (Allowed values: "username", "email") | `"username"` | | `value` | `string` | Yes | No | Value returned by the operation. (Maximum length: 2048 characters.) | `"100.00"` | ```json { "field": "username", "value": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.username` | `string` | Yes | No | username for this profile. | `"owner"` | | `data.email` | `string` | Yes | No | Email address associated with the identity. | `"owner@example.com"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "username": "owner", "email": "owner@example.com" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/profile" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "field": "username", "value": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/profile", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, "Content-Type": "application/json", }, body: JSON.stringify({ "field": "username", "value": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/profile failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Create a profile avatar upload **POST** `/v1/profile/avatar-uploads` Create a profile avatar upload. - Canonical URL: [https://docs.nqd.app/v1/reference/profile/avatar-uploads/create](https://docs.nqd.app/v1/reference/profile/avatar-uploads/create) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `mime` | `string` | Yes | No | mime for this profile. (Allowed values: "image/png", "image/jpeg", "image/jpg", "image/svg+xml") | `"image/png"` | | `size` | `number` | Yes | No | size for this profile. (maximum 2097152, greater than 0) | `100` | ```json { "mime": "image/png", "size": 100 } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.signedUrl` | `string` | Yes | No | signed url for this profile. | `"https://example.com/hooks/nqd"` | | `data.publicUrl` | `string` | Yes | No | public url for this profile. | `"https://example.com/hooks/nqd"` | ```json { "data": { "signedUrl": "https://example.com/hooks/nqd", "publicUrl": "https://example.com/hooks/nqd" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/profile/avatar-uploads" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "mime": "image/png", "size": 100 }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/profile/avatar-uploads", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, "Content-Type": "application/json", }, body: JSON.stringify({ "mime": "image/png", "size": 100 }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/profile/avatar-uploads failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read profile preferences **GET** `/v1/profile/preferences` Read your profile preferences. - Canonical URL: [https://docs.nqd.app/v1/reference/profile/preferences/list](https://docs.nqd.app/v1/reference/profile/preferences/list) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[scope]` | `string` | No | No | Filter profile-preferences by scope. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[schemaVersion]` | `string` | No | No | Filter profile-preferences by schemaVersion. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.1"` | | `filter[revision]` | `string` | No | No | Filter profile-preferences by revision. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.1"` | | `filter[updatedAt]` | `string` | No | No | Filter profile-preferences by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"scope,preferences"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"scope.asc,schemaVersion.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].scope` | `string` | Yes | No | scope for this profile preference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data[].preferences` | `object` | Yes | No | preferences for this profile preference. | — | | `data[].schemaVersion` | `number` | Yes | No | schema version for this profile preference. | `100` | | `data[].revision` | `number` | Yes | No | revision for this profile preference. | `100` | | `data[].updatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "scope": "Consulting services", "preferences": {}, "schemaVersion": 100, "revision": 100 } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/profile/preferences" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/profile/preferences", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/profile/preferences failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Save profile preferences **PUT** `/v1/profile/preferences` Save profile preferences. - Canonical URL: [https://docs.nqd.app/v1/reference/profile/preferences/upsert](https://docs.nqd.app/v1/reference/profile/preferences/upsert) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `profileId` | `string` | Yes | No | ID of the related profile. (Maximum length: 2048 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `scope` | `string` | Yes | No | scope for this profile preference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `revision` | `number` | Yes | No | revision for this profile preference. (minimum 0) | `100` | | `patch` | `object` | Yes | No | patch for this profile preference. | — | ```json { "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "scope": "Consulting services", "revision": 100, "patch": {} } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.conflict` | `boolean` | Yes | No | conflict for this profile preference. | `true` | | `data.record` | `object` | Yes | No | record for this profile preference. | — | | `data.record.scope` | `string` | Yes | No | scope within record. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.record.preferences` | `object` | Yes | No | preferences within record. | — | | `data.record.schemaVersion` | `number` | Yes | No | schema version within record. | `100` | | `data.record.revision` | `number` | Yes | No | revision within record. | `100` | | `data.record.updatedAt` | `string` | No | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "conflict": true, "record": { "scope": "Consulting services", "preferences": {}, "schemaVersion": 100, "revision": 100 } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/profile/preferences" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "scope": "Consulting services", "revision": 100, "patch": {} }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/profile/preferences", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, "Content-Type": "application/json", }, body: JSON.stringify({ "profileId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "scope": "Consulting services", "revision": 100, "patch": {} }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/profile/preferences failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List projects **GET** `/v1/projects` Retrieve matching projects. - Canonical URL: [https://docs.nqd.app/v1/reference/projects/list](https://docs.nqd.app/v1/reference/projects/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter projects by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[clientId]` | `string` | No | No | Filter projects by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[name]` | `string` | No | No | Filter projects by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter projects by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[website]` | `string` | No | No | Filter projects by website. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter projects by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[createdAt]` | `string` | No | No | Filter projects by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter projects by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,clientId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,clientId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string` | Yes | Yes | website for this project. | `"https://example.com/hooks/nqd"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].clientName` | `string` | No | Yes | client name for this project. | `"Consulting services"` | | `data[].clientWebsite` | `string[]` | No | Yes | client website for this project. | `["Consulting services"]` | | `data[].clientType` | `string` | No | Yes | client type for this project. (Allowed values: "company", "individual", "government") | `"company"` | | `data[].contacts` | `number \| string` | No | Yes | contacts for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].invoices` | `number \| string` | No | Yes | invoices for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].invoiceAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].payouts` | `number \| string` | No | Yes | payouts for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].payoutAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].paidPayouts` | `number \| string` | No | Yes | paid payouts for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].paidPayoutAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].pendingPayouts` | `number \| string` | No | Yes | pending payouts for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].pendingPayoutAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].invoicePendingCount` | `number \| string` | No | Yes | invoice pending count for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].invoicePaidCount` | `number \| string` | No | Yes | invoice paid count for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].invoiceCancelledCount` | `number \| string` | No | Yes | invoice cancelled count for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].payoutPendingCount` | `number \| string` | No | Yes | payout pending count for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].payoutPaidCount` | `number \| string` | No | Yes | payout paid count for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].payoutCancelledCount` | `number \| string` | No | Yes | payout cancelled count for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].pendingAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].paidAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].cancelledAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].invoicePendingAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].invoicePaidAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].invoiceCancelledAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].payoutPendingAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].payoutPaidAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].payoutCancelledAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].pendingRecords` | `number \| string` | No | Yes | pending records for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].paidRecords` | `number \| string` | No | Yes | paid records for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].cancelledRecords` | `number \| string` | No | Yes | cancelled records for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].expenses` | `number \| string` | No | Yes | expenses for this project. Alternatives: number alternative 1, string alternative 2. | `100` | | `data[].expenseAmount` | `number \| string \| string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data[].contactItems` | `object[]` | No | Yes | contact items for this project. | — | | `data[].contactItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].contactItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].invoiceItems` | `object[]` | No | Yes | invoice items for this project. | — | | `data[].invoiceItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].invoiceItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].payoutItems` | `object[]` | No | Yes | payout items for this project. | — | | `data[].payoutItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].payoutItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].invoicePendingItems` | `object[]` | No | Yes | invoice pending items for this project. | — | | `data[].invoicePendingItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].invoicePendingItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].invoicePaidItems` | `object[]` | No | Yes | invoice paid items for this project. | — | | `data[].invoicePaidItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].invoicePaidItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].invoiceCancelledItems` | `object[]` | No | Yes | invoice cancelled items for this project. | — | | `data[].invoiceCancelledItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].invoiceCancelledItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].payoutPendingItems` | `object[]` | No | Yes | payout pending items for this project. | — | | `data[].payoutPendingItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].payoutPendingItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].payoutPaidItems` | `object[]` | No | Yes | payout paid items for this project. | — | | `data[].payoutPaidItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].payoutPaidItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].payoutCancelledItems` | `object[]` | No | Yes | payout cancelled items for this project. | — | | `data[].payoutCancelledItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].payoutCancelledItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].paidPayoutItems` | `object[]` | No | Yes | paid payout items for this project. | — | | `data[].paidPayoutItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].paidPayoutItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].pendingPayoutItems` | `object[]` | No | Yes | pending payout items for this project. | — | | `data[].pendingPayoutItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].pendingPayoutItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].expenseItems` | `object[]` | No | Yes | expense items for this project. | — | | `data[].expenseItems[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].expenseItems[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "clientId": null, "name": "NQD record", "description": "Consulting services for January 2026", "website": "https://example.com/hooks/nqd", "tags": [ "equipment" ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/projects" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/projects", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/projects failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve project **GET** `/v1/projects/{projectId}` Return the addressed project. - Canonical URL: [https://docs.nqd.app/v1/reference/projects/retrieve](https://docs.nqd.app/v1/reference/projects/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `projectId` | `string` | Yes | No | An opaque project resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.website` | `string` | Yes | Yes | website for this project. | `"https://example.com/hooks/nqd"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "clientId": null, "name": "NQD record", "description": "Consulting services for January 2026", "website": "https://example.com/hooks/nqd", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create projects **POST** `/v1/projects` Create projects from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/projects/create](https://docs.nqd.app/v1/reference/projects/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string` | No | Yes | website for this project. (Maximum length: 10000 characters.) | `"https://example.com/hooks/nqd"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | ```json [ { "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string` | Yes | Yes | website for this project. | `"https://example.com/hooks/nqd"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "clientId": null, "name": "NQD record", "description": "Consulting services for January 2026", "website": "https://example.com/hooks/nqd", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/projects" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/projects", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/projects failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert project **PUT** `/v1/projects/{projectId}` Create or update the addressed project. - Canonical URL: [https://docs.nqd.app/v1/reference/projects/upsert](https://docs.nqd.app/v1/reference/projects/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `projectId` | `string` | Yes | No | An opaque project resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string` | No | Yes | website for this project. (Maximum length: 10000 characters.) | `"https://example.com/hooks/nqd"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | ```json { "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.website` | `string` | Yes | Yes | website for this project. | `"https://example.com/hooks/nqd"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "clientId": null, "name": "NQD record", "description": "Consulting services for January 2026", "website": "https://example.com/hooks/nqd", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete project **DELETE** `/v1/projects/{projectId}` Delete project. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/projects/delete](https://docs.nqd.app/v1/reference/projects/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `projectId` | `string` | Yes | No | An opaque project resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/projects/01JQ2T5Y5Q3R8W9N6M4K2H7P1D failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert projects in a batch **PUT** `/v1/projects` Upsert projects atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/projects/bulk-upsert](https://docs.nqd.app/v1/reference/projects/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string` | No | Yes | website for this project. (Maximum length: 10000 characters.) | `"https://example.com/hooks/nqd"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | ```json [ { "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string` | Yes | Yes | website for this project. | `"https://example.com/hooks/nqd"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "clientId": null, "name": "NQD record", "description": "Consulting services for January 2026", "website": "https://example.com/hooks/nqd", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/projects" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/projects", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "clientId": null, "description": "Consulting services for January 2026", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/projects failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Read the workspace balance sheet **GET** `/v1/reports/balance-sheet` Read the workspace balance sheet. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/balance-sheet](https://docs.nqd.app/v1/reference/reports/balance-sheet) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.report` | `object` | Yes | No | report for this report. | — | | `data.report.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.report.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.report.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.report.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.report.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.report.metrics` | `object` | Yes | No | metrics within report. | — | | `data.report.metrics.revenue` | `number` | Yes | No | revenue within metrics. | `100` | | `data.report.metrics.paidRevenue` | `number` | Yes | No | paid revenue within metrics. | `100` | | `data.report.metrics.outstandingRevenue` | `number` | Yes | No | outstanding revenue within metrics. | `100` | | `data.report.metrics.expenses` | `number` | Yes | No | expenses within metrics. | `100` | | `data.report.metrics.recurringExpenses` | `number` | Yes | No | recurring expenses within metrics. | `100` | | `data.report.metrics.payouts` | `number` | Yes | No | payouts within metrics. | `100` | | `data.report.metrics.paidPayouts` | `number` | Yes | No | paid payouts within metrics. | `100` | | `data.report.metrics.pendingPayouts` | `number` | Yes | No | pending payouts within metrics. | `100` | | `data.report.metrics.netIncome` | `number` | Yes | No | net income within metrics. | `100` | | `data.report.metrics.cashOnHand` | `number` | Yes | No | cash on hand within metrics. | `100` | | `data.report.inputVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.report.outputVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.report.netVatPosition` | `number` | Yes | No | net vat position within report. | `100` | | `data.report.expensePayable` | `number` | Yes | No | expense payable within report. | `100` | | `data.report.assetPayable` | `number` | Yes | No | asset payable within report. | `100` | | `data.report.customerAdvances` | `number` | Yes | No | customer advances within report. | `100` | | `data.report.supplierAdvances` | `number` | Yes | No | supplier advances within report. | `100` | | `data.report.cashOverdraft` | `number` | Yes | No | cash overdraft within report. | `100` | | `data.report.vatPaid` | `number` | Yes | No | vat paid within report. | `100` | | `data.report.operatingExpenses` | `number` | Yes | No | operating expenses within report. | `100` | | `data.report.taxExpense` | `number` | Yes | No | tax expense within report. | `100` | | `data.report.fixedAssets` | `number` | Yes | No | fixed assets within report. | `100` | | `data.report.assetCarryingValueStatus` | `string` | Yes | No | asset carrying value status within report. (Allowed values: "resolved", "unresolved") | `"resolved"` | | `data.report.unresolvedAssetCount` | `number` | Yes | No | unresolved asset count within report. | `100` | | `data.report.payables` | `object[]` | Yes | No | payables within report. | — | | `data.report.payables[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.payables[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.payables[].modifierId` | `string` | Yes | No | ID of the related modifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.report.payables[].purpose` | `string` | Yes | No | purpose within payables. (Allowed values: "custom", "vat", "zakah") | `"custom"` | | `data.report.payables[].recipient` | `string` | Yes | No | recipient within payables. | `"Consulting services"` | | `data.report.payables[].modifierName` | `string` | Yes | No | modifier name within payables. | `"Consulting services"` | | `data.report.payables[].opening` | `number` | Yes | No | opening within payables. | `100` | | `data.report.payables[].accrued` | `number` | Yes | No | accrued within payables. | `100` | | `data.report.payables[].paid` | `number` | Yes | No | paid within payables. | `100` | | `data.report.payables[].remaining` | `number` | Yes | No | remaining within payables. | `0` | | `data.report.payables[].vat` | `object` | No | Yes | Value-added tax amount. | — | | `data.report.payables[].vat.output` | `number` | Yes | No | output within vat. | `100` | | `data.report.payables[].vat.input` | `number` | Yes | No | input within vat. | `100` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.asOfDate` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "report": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "metrics": { "revenue": 100, "paidRevenue": 100, "outstandingRevenue": 100, "expenses": 100, "recurringExpenses": 100, "payouts": 100, "paidPayouts": 100, "pendingPayouts": 100, "netIncome": 100, "cashOnHand": 100 }, "inputVat": 100, "outputVat": 100, "netVatPosition": 100, "expensePayable": 100, "assetPayable": 100, "customerAdvances": 100, "supplierAdvances": 100, "cashOverdraft": 100, "vatPaid": 100, "operatingExpenses": 100, "taxExpense": 100, "fixedAssets": 100, "assetCarryingValueStatus": "resolved", "unresolvedAssetCount": 100, "payables": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "purpose": "custom", "recipient": "Consulting services", "modifierName": "Consulting services", "opening": 100, "accrued": 100, "paid": 100, "remaining": 0 } ] }, "fiscalStart": "2026-01-01", "defaultRange": { "end": "2026-01-31", "start": "2026-01-01" }, "asOfDate": "Consulting services", "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/balance-sheet" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/balance-sheet", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/balance-sheet failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read workspace cash flow **GET** `/v1/reports/cash-flow` Read workspace cash flow. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/cash-flow](https://docs.nqd.app/v1/reference/reports/cash-flow) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.report` | `object` | Yes | No | report for this report. | — | | `data.report.cashflow` | `object` | Yes | No | cashflow within report. | — | | `data.report.cashflow.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.report.cashflow.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.report.cashflow.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.cashflow.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.report.cashflow.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.cashflow.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.cashflow.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.report.cashflow.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.report.cashflow.months` | `string[]` | Yes | No | months within cashflow. | `["Consulting services"]` | | `data.report.cashflow.rows` | `object[]` | Yes | No | rows within cashflow. | — | | `data.report.cashflow.rows[].month` | `string` | Yes | No | month within rows. | `"2026-01"` | | `data.report.cashflow.rows[].inflow` | `number` | Yes | No | inflow within rows. | `100` | | `data.report.cashflow.rows[].outflow` | `number` | Yes | No | outflow within rows. | `100` | | `data.report.cashflow.rows[].net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.report.cashflow.granularity` | `string` | Yes | No | granularity within cashflow. (Allowed values: "day", "month", "year") | `"day"` | | `data.report.cashflow.openingCash` | `number` | Yes | No | opening cash within cashflow. | `100` | | `data.report.cashflow.closingCash` | `number` | Yes | No | closing cash within cashflow. | `100` | | `data.report.cashflow.vatPaid` | `number` | Yes | No | vat paid within cashflow. | `100` | | `data.report.cashflow.vatBalance` | `number` | Yes | No | vat balance within cashflow. | `100` | | `data.report.cashflow.vatPayable` | `number` | Yes | No | vat payable within cashflow. | `100` | | `data.report.cashflow.projectedRows` | `object[]` | No | Yes | projected rows within cashflow. | — | | `data.report.cashflow.projectedRows[].month` | `string` | Yes | No | month within projected rows. | `"2026-01"` | | `data.report.cashflow.projectedRows[].inflow` | `number` | Yes | No | inflow within projected rows. | `100` | | `data.report.cashflow.projectedRows[].outflow` | `number` | Yes | No | outflow within projected rows. | `100` | | `data.report.cashflow.projectedRows[].net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.report.cashflow.projections` | `object[]` | No | Yes | projections within cashflow. | — | | `data.report.cashflow.projections[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.report.cashflow.projections[].sourceId` | `string` | Yes | No | ID of the related source. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.report.cashflow.projections[].kind` | `string` | Yes | No | kind within projections. (Allowed values: "invoice", "expense", "payout") | `"invoice"` | | `data.report.cashflow.projections[].status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "scheduled", "overdue", "unavailable") | `"scheduled"` | | `data.report.cashflow.projections[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.cashflow.projections[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.report.cashflow.projections[].partyId` | `string` | Yes | Yes | ID of the related party. | `"Consulting services"` | | `data.report.cashflow.projections[].materializedSourceId` | `string` | No | Yes | ID of the related materialized source. | `"Consulting services"` | | `data.report.cashflow.projections[].currencyCode` | `string` | Yes | No | currency code within projections. | `"SAR"` | | `data.report.cashflow.projections[].amount` | `number` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.report.cashflow.projections[].reportingAmount` | `number` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.report.cashflow.projections[].context` | `object` | No | Yes | context within projections. | — | | `data.report.cashflow.projections[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data.report.cashflow.projections[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data.report.cashflow.projections[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data.report.cashflow.projections[].reason` | `string` | No | Yes | Machine-readable reason for the validation issue. (Allowed values: "missing_value", "missing_conversion") | `"missing_value"` | | `data.report.cashflow.projections[].occurrenceAt` | `string` | Yes | No | ISO 8601 timestamp for occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.report.cashflow.projectedClosingCash` | `number` | No | Yes | projected closing cash within cashflow. | `100` | | `data.report.cashflow.consolidated` | `object` | Yes | Yes | consolidated within cashflow. | — | | `data.report.cashflow.consolidated.metrics` | `object` | Yes | No | metrics within consolidated. | — | | `data.report.cashflow.consolidated.metrics.revenue` | `number` | Yes | No | revenue within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.paidRevenue` | `number` | Yes | No | paid revenue within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.outstandingRevenue` | `number` | Yes | No | outstanding revenue within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.expenses` | `number` | Yes | No | expenses within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.recurringExpenses` | `number` | Yes | No | recurring expenses within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.payouts` | `number` | Yes | No | payouts within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.paidPayouts` | `number` | Yes | No | paid payouts within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.pendingPayouts` | `number` | Yes | No | pending payouts within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.netIncome` | `number` | Yes | No | net income within metrics. | `100` | | `data.report.cashflow.consolidated.metrics.cashOnHand` | `number` | Yes | No | cash on hand within metrics. | `100` | | `data.report.cashflow.consolidated.recognizedTaxInflow` | `number` | Yes | No | recognized tax inflow within consolidated. | `100` | | `data.report.cashflow.consolidated.recognizedTaxOutflow` | `number` | Yes | No | recognized tax outflow within consolidated. | `100` | | `data.report.cashflow.consolidated.capitalizedCost` | `number` | Yes | No | capitalized cost within consolidated. | `100` | | `data.report.cashflow.consolidated.assetCarryingValue` | `number` | Yes | No | asset carrying value within consolidated. | `100` | | `data.report.cashflow.consolidated.committedResult` | `number` | Yes | No | committed result within consolidated. | `100` | | `data.report.cashflow.consolidated.cashResult` | `number` | Yes | No | cash result within consolidated. | `100` | | `data.report.cashflow.consolidated.netIncomeBeforeTax` | `number` | Yes | No | net income before tax within consolidated. | `100` | | `data.report.cashflow.consolidated.netIncomeAfterTax` | `number` | Yes | No | net income after tax within consolidated. | `100` | | `data.filters` | `object` | Yes | No | filters for this report. | — | | `data.filters.start` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.filters.end` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | ```json { "data": { "report": { "cashflow": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "months": [ "Consulting services" ], "rows": [ { "month": "2026-01", "inflow": 100, "outflow": 100, "net": 100 } ], "granularity": "day", "openingCash": 100, "closingCash": 100, "vatPaid": 100, "vatBalance": 100, "vatPayable": 100, "consolidated": { "metrics": { "revenue": 100, "paidRevenue": 100, "outstandingRevenue": 100, "expenses": 100, "recurringExpenses": 100, "payouts": 100, "paidPayouts": 100, "pendingPayouts": 100, "netIncome": 100, "cashOnHand": 100 }, "recognizedTaxInflow": 100, "recognizedTaxOutflow": 100, "capitalizedCost": 100, "assetCarryingValue": 100, "committedResult": 100, "cashResult": 100, "netIncomeBeforeTax": 100, "netIncomeAfterTax": 100 } } }, "filters": {}, "fiscalStart": "2026-01-01", "defaultRange": { "end": "2026-01-31", "start": "2026-01-01" } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/cash-flow" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/cash-flow", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/cash-flow failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read the workspace cashbook **GET** `/v1/reports/cashbook` Read effective cash transactions for start through end, optionally scoped to a bank account and source selections. Chronological pages retain the running book balance. This is not a bank reconciliation. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/cashbook](https://docs.nqd.app/v1/reference/reports/cashbook) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | | `page` | `string` | No | No | One-based page number for this resource directory. (pattern ^[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?$) | `"25"` | | `pageSize` | `string` | No | No | Optional page size filter or query option. (pattern ^[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?$) | `"1"` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-01"` | | `data.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-31"` | | `data.selectedBankAccountId` | `string` | Yes | Yes | ID of the related selected bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.reportingCurrency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.reportingCurrency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.reportingCurrency.code` | `string` | Yes | No | Stable machine-readable error or resource code. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.reportingCurrency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.reportingCurrency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.reportingCurrency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.reportingCurrency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.accounts` | `object[]` | Yes | No | accounts for this report. | — | | `data.accounts[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `data.accounts[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data.accounts[].archived` | `boolean` | Yes | No | archived within accounts. | `true` | | `data.openingBalance` | `number` | Yes | No | opening balance for this report. | `100` | | `data.periodInbound` | `number` | Yes | No | period inbound for this report. | `100` | | `data.periodOutbound` | `number` | Yes | No | period outbound for this report. | `100` | | `data.closingBalance` | `number` | Yes | No | closing balance for this report. | `100` | | `data.rows` | `object[]` | Yes | No | rows for this report. | — | | `data.rows[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.rows[].source` | `object` | Yes | Yes | source within rows. | — | | `data.rows[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.rows[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data.rows[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data.rows[].direction` | `string` | Yes | No | direction within rows. (Allowed values: "inbound", "outbound") | `"inbound"` | | `data.rows[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.rows[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.rows[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.rows[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.rows[].reportingAmount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.rows[].reportingCurrency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.rows[].reportingCurrency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.rows[].reportingCurrency.code` | `string` | Yes | No | Stable machine-readable error or resource code. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.rows[].reportingCurrency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.rows[].reportingCurrency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].reportingCurrency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].reportingCurrency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.rows[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.rows[].accountLabel` | `string` | Yes | Yes | account label within rows. | `"Consulting services"` | | `data.rows[].context` | `object` | Yes | No | context within rows. | — | | `data.rows[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data.rows[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data.rows[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data.rows[].runningBalance` | `number` | Yes | No | running balance within rows. | `100` | | `data.rows[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.page` | `number` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | `1` | | `data.pageSize` | `number` | Yes | No | page size for this report. (minimum 1, maximum 500) | `1` | | `data.totalRows` | `number` | Yes | No | total rows for this report. | `100` | | `data.hasNext` | `boolean` | Yes | No | has next for this report. | `true` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "start": "2026-01-01", "end": "2026-01-31", "selectedBankAccountId": "Consulting services", "reportingCurrency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "Consulting services", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "accounts": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1G", "label": "Operating account", "archived": true } ], "openingBalance": 100, "periodInbound": 100, "periodOutbound": 100, "closingBalance": 100, "rows": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "type": "invoice" }, "amount": "100.00", "direction": "inbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "reportingAmount": 100, "reportingCurrency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "Consulting services", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "bankAccountId": null, "accountLabel": "Consulting services", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "runningBalance": 100, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": 1, "pageSize": 1, "totalRows": 100, "hasNext": true, "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/cashbook?start=2026-01-15&end=2026-01-15" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/cashbook", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); url.searchParams.append("start", "2026-01-15"); url.searchParams.append("end", "2026-01-15"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/cashbook failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read the workspace financial center report **GET** `/v1/reports/center` Read the workspace financial center report. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/center](https://docs.nqd.app/v1/reference/reports/center) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.invoiceCounts` | `object` | Yes | No | invoice counts for this report. | — | | `data.invoiceCounts.draft` | `number` | Yes | No | draft within invoice counts. | `100` | | `data.invoiceCounts.pending` | `number` | Yes | No | pending within invoice counts. | `100` | | `data.payoutCounts` | `object` | Yes | No | payout counts for this report. | — | | `data.payoutCounts.pending` | `number` | Yes | No | pending within payout counts. | `100` | | `data.expenseOptions` | `object` | Yes | No | expense options for this report. | — | | `data.expenseOptions.tagOptions` | `object[]` | Yes | No | tag options within expense options. | — | | `data.expenseOptions.tagOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.expenseOptions.tagOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.expenseOptions.vendorOptions` | `object[]` | Yes | No | vendor options within expense options. | — | | `data.expenseOptions.vendorOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.expenseOptions.vendorOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.expenseOptions.clientOptions` | `object[]` | Yes | No | client options within expense options. | — | | `data.expenseOptions.clientOptions[].id` | `string` | Yes | Yes | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.expenseOptions.clientOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.expenseOptions.projectOptions` | `object[]` | Yes | No | project options within expense options. | — | | `data.expenseOptions.projectOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.expenseOptions.projectOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.expenseOptions.projectOptionsByClient` | `object` | Yes | No | project options by client within expense options. | — | | `data.expenseOptions.recurringExpenseOptions` | `object[]` | Yes | No | recurring expense options within expense options. | — | | `data.expenseOptions.recurringExpenseOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.expenseOptions.recurringExpenseOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.expenseOptions.recurringExpenseOptionsByVendor` | `object` | Yes | No | recurring expense options by vendor within expense options. | — | | `data.expenseOptions.currencyOptions` | `object[]` | Yes | No | currency options within expense options. | — | | `data.expenseOptions.currencyOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.expenseOptions.currencyOptions[].code` | `string` | Yes | No | Stable machine-readable error or resource code. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.expenseOptions.currencyOptions[].conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.expenseOptions.currencyOptions[].conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.expenseOptions.currencyOptions[].conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.expenseOptions.currencyOptions[].conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.expenseOptions.currencyOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.expenseOptions.modifierOptions` | `object[]` | Yes | No | modifier options within expense options. | — | | `data.expenseOptions.modifierOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.expenseOptions.modifierOptions[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.expenseOptions.modifierOptions[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"NQD record"` | | `data.expenseOptions.modifierOptions[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `data.expenseOptions.modifierOptions[].entryIndex` | `number` | No | Yes | entry index within modifier options. | `100` | | `data.expenseOptions.modifierOptions[].value` | `string` | Yes | No | Value returned by the operation. (Maximum length: 128 characters.) | `"100.00"` | | `data.expenseOptions.modifierOptions[].currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.expenseOptions.modifierOptions[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.expenseOptions.modifierOptions[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.expenseOptions.modifierOptions[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.expenseOptions.modifierOptions[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.expenseOptions.modifierOptions[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.expenseOptions.modifierOptions[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.expenseOptions.bankAccountOptions` | `object[]` | Yes | No | bank account options within expense options. | — | | `data.expenseOptions.bankAccountOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.expenseOptions.bankAccountOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.expenseOptions.bankAccountOptions[].archived` | `boolean` | No | Yes | archived within bank account options. | `true` | | `data.expenseOptions.defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. | `null` | | `data.incomeOptions` | `object` | Yes | No | income options for this report. | — | | `data.incomeOptions.defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. | `null` | | `data.incomeOptions.accountOptions` | `object[]` | Yes | No | account options within income options. | — | | `data.incomeOptions.accountOptions[].archived` | `boolean` | Yes | No | archived within account options. | `true` | | `data.incomeOptions.accountOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.incomeOptions.accountOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.incomeOptions.currencyOptions` | `object[]` | Yes | No | currency options within income options. | — | | `data.incomeOptions.currencyOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.incomeOptions.currencyOptions[].code` | `string` | Yes | No | Stable machine-readable error or resource code. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.incomeOptions.currencyOptions[].conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.incomeOptions.currencyOptions[].conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.incomeOptions.currencyOptions[].conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.incomeOptions.currencyOptions[].conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.incomeOptions.currencyOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.incomeOptions.clientOptions` | `object[]` | Yes | No | client options within income options. | — | | `data.incomeOptions.clientOptions[].id` | `string` | Yes | Yes | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.incomeOptions.clientOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.incomeOptions.projectOptions` | `object[]` | Yes | No | project options within income options. | — | | `data.incomeOptions.projectOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.incomeOptions.projectOptions[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.incomeOptions.projectOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.incomeOptions.contactOptions` | `object[]` | Yes | No | contact options within income options. | — | | `data.incomeOptions.contactOptions[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.incomeOptions.contactOptions[].clientId` | `string` | Yes | Yes | Optional client reference. Null means the current workspace owns the record; do not create a placeholder client. | `null` | | `data.incomeOptions.contactOptions[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.incomeOptions.tagOptions` | `string[]` | Yes | No | tag options within income options. | `["Consulting services"]` | | `data.currencies` | `object[]` | Yes | No | currencies for this report. | — | | `data.currencies[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currencies[].code` | `string` | Yes | No | Stable machine-readable error or resource code. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currencies[].conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currencies[].conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currencies[].conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currencies[].conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.currencies[].name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.modifiers` | `object[]` | Yes | No | Modifiers applied to one entry or the whole source. Supported values are signed fixed amounts or percentages, such as \`15.00%\` or \`-25.00\`; arbitrary multiplication and division are not supported. | — | | `data.modifiers[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.modifiers[].appliedId` | `string` | No | Yes | Stable identity of this saved modifier application. Preserve it when updating a financial record, including repeated uses of the same catalog modifier. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.modifiers[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 10000 characters.) | `"VAT"` | | `data.modifiers[].description` | `string` | No | Yes | Optional human-readable description of the record. (Maximum length: 10000 characters.) | `"Value added tax"` | | `data.modifiers[].entryIndex` | `number` | No | Yes | entry index within modifiers. | `100` | | `data.modifiers[].value` | `string` | Yes | No | Modifier value. A trailing \`%\` marks a percentage; a leading \`-\` marks a decrease. Modifiers support fixed or percentage adjustments, not arbitrary multiplication or division. (Maximum length: 128 characters.) | `"15.00%"` | | `data.modifiers[].currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.modifiers[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.modifiers[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.modifiers[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.modifiers[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.modifiers[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.modifiers[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.taxModifierId` | `string` | Yes | Yes | Identifier of the workspace payable modifier used to calculate VAT. Apply the matching modifier in the flat modifiers array. | `"100.00"` | | `data.templates` | `object[]` | Yes | No | templates for this report. | — | | `data.templates[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1H"` | | `data.templates[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.templates[].description` | `string` | Yes | No | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.templates[].unitCode` | `string` | Yes | No | Unit code from the workspace catalog. | `"hour"` | | `data.templates[].quantity` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"2.00"` | | `data.templates[].pricePerUnit` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `data.templates[].currencyId` | `string` | Yes | No | Currency identifier for the amount. It selects the currency metadata used by the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.templates[].modifierIds` | `string[]` | No | Yes | Ordered modifier identifiers applied to the record. (at most 1000 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1J"]` | | `data.workspaceInfo` | `object` | Yes | Yes | workspace info for this report. | — | | `data.workspaceInfo.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `data.workspaceInfo.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.workspaceInfo.email` | `string` | Yes | Yes | Email address associated with the identity. | `"owner@example.com"` | | `data.workspaceInfo.phone` | `string` | Yes | Yes | phone within workspace info. | `"+966500000000"` | | `data.payoutInvoices` | `object` | Yes | No | payout invoices for this report. | — | | `data.payoutInvoices.options` | `object[]` | Yes | No | options within payout invoices. | — | | `data.payoutInvoices.options[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.payoutInvoices.options[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.payoutInvoices.optionsByProject` | `object` | Yes | No | options by project within payout invoices. | — | | `data.payoutInvoices.optionsByClient` | `object` | Yes | No | options by client within payout invoices. | — | | `data.reportingCurrency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.reportingCurrency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.reportingCurrency.code` | `string` | Yes | No | Stable machine-readable error or resource code. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.reportingCurrency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.reportingCurrency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.reportingCurrency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.reportingCurrency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.reportingCurrency.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.invoiceQueue` | `object[]` | Yes | No | invoice queue for this report. | — | | `data.invoiceQueue[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.invoiceQueue[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.invoiceQueue[].shortId` | `string` | Yes | No | ID of the related short. | `"INV-0001"` | | `data.invoiceQueue[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data.payoutQueue` | `object[]` | Yes | No | payout queue for this report. | — | | `data.payoutQueue[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data.payoutQueue[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.payoutQueue[].pendedAt` | `string` | Yes | Yes | ISO 8601 timestamp for pended. | `null` | | `data.cash` | `object` | Yes | Yes | cash for this report. | — | | `data.cash.inbound` | `number` | Yes | No | inbound within cash. | `100` | | `data.cash.outbound` | `number` | Yes | No | outbound within cash. | `100` | | `data.stats` | `object` | Yes | No | stats for this report. | — | | `data.stats.overdueInvoices` | `number` | Yes | No | overdue invoices within stats. | `100` | | `data.stats.outstandingInvoices` | `number` | Yes | Yes | outstanding invoices within stats. | `100` | | `data.stats.outstandingPayouts` | `number` | Yes | Yes | outstanding payouts within stats. | `100` | | `data.stats.transactionsThisMonth` | `number` | Yes | No | transactions this month within stats. | `100` | | `data.stats.incomeThisMonth` | `number` | Yes | Yes | income this month within stats. | `100` | | `data.stats.expensesThisMonth` | `number` | Yes | Yes | expenses this month within stats. | `100` | | `data.stats.activeClients` | `number` | Yes | No | active clients within stats. | `100` | | `data.stats.activeProjects` | `number` | Yes | No | active projects within stats. | `100` | | `data.stats.activeVendors` | `number` | Yes | No | active vendors within stats. | `100` | | `data.stats.activeContacts` | `number` | Yes | No | active contacts within stats. | `100` | | `data.stats.activeEntries` | `number` | Yes | No | active entries within stats. | `100` | | `data.stats.assets` | `number` | Yes | No | assets within stats. | `100` | | `data.stats.recurringInvoices` | `number` | Yes | No | recurring invoices within stats. | `100` | | `data.stats.recurringExpenses` | `number` | Yes | No | recurring expenses within stats. | `100` | | `data.stats.recurringPayouts` | `number` | Yes | No | recurring payouts within stats. | `100` | | `data.monthStart` | `string` | Yes | No | month start for this report. | `"Consulting services"` | | `data.monthEnd` | `string` | Yes | No | month end for this report. | `"Consulting services"` | ```json { "data": { "invoiceCounts": { "draft": 100, "pending": 100 }, "payoutCounts": { "pending": 100 }, "expenseOptions": { "tagOptions": [ { "id": "Consulting services", "name": "NQD record" } ], "vendorOptions": [ { "id": "Consulting services", "name": "NQD record" } ], "clientOptions": [ { "id": "Consulting services", "name": "NQD record" } ], "projectOptions": [ { "id": "Consulting services", "name": "NQD record" } ], "projectOptionsByClient": {}, "recurringExpenseOptions": [ { "id": "Consulting services", "name": "NQD record" } ], "recurringExpenseOptionsByVendor": {}, "currencyOptions": [ { "id": "Consulting services", "code": "Consulting services", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "NQD record" } ], "modifierOptions": [ { "id": "Consulting services", "name": "NQD record", "value": "100.00", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } } } ], "bankAccountOptions": [ { "id": "Consulting services", "name": "NQD record" } ], "defaultCurrencyId": null }, "incomeOptions": { "defaultCurrencyId": null, "accountOptions": [ { "archived": true, "id": "Consulting services", "name": "NQD record" } ], "currencyOptions": [ { "id": "Consulting services", "code": "Consulting services", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "NQD record" } ], "clientOptions": [ { "id": "Consulting services", "name": "NQD record" } ], "projectOptions": [ { "id": "Consulting services", "clientId": null, "name": "NQD record" } ], "contactOptions": [ { "id": "Consulting services", "clientId": null, "name": "NQD record" } ], "tagOptions": [ "Consulting services" ] }, "currencies": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" } ], "modifiers": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "name": "VAT", "value": "15.00%", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } } } ], "taxModifierId": "100.00", "templates": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1H", "name": "NQD record", "description": "Consulting services for January 2026", "unitCode": "hour", "quantity": "2.00", "pricePerUnit": "100.00", "currencyId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F" } ], "workspaceInfo": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1A", "name": "NQD record", "email": "owner@example.com", "phone": "+966500000000" }, "payoutInvoices": { "options": [ { "id": "Consulting services", "name": "NQD record" } ], "optionsByProject": {}, "optionsByClient": {} }, "reportingCurrency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "Consulting services", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "NQD record" }, "invoiceQueue": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "name": "NQD record", "shortId": "INV-0001", "pendedAt": null } ], "payoutQueue": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "projectId": null, "pendedAt": null } ], "cash": { "inbound": 100, "outbound": 100 }, "stats": { "overdueInvoices": 100, "outstandingInvoices": 100, "outstandingPayouts": 100, "transactionsThisMonth": 100, "incomeThisMonth": 100, "expensesThisMonth": 100, "activeClients": 100, "activeProjects": 100, "activeVendors": 100, "activeContacts": 100, "activeEntries": 100, "assets": 100, "recurringInvoices": 100, "recurringExpenses": 100, "recurringPayouts": 100 }, "monthStart": "Consulting services", "monthEnd": "Consulting services" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/center" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/center", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/center failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read the workspace income statement **GET** `/v1/reports/income-statement` Read the workspace income statement. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/income-statement](https://docs.nqd.app/v1/reference/reports/income-statement) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.report` | `object` | Yes | No | report for this report. | — | | `data.report.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.report.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.report.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.report.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.report.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.report.metrics` | `object` | Yes | No | metrics within report. | — | | `data.report.metrics.revenue` | `number` | Yes | No | revenue within metrics. | `100` | | `data.report.metrics.paidRevenue` | `number` | Yes | No | paid revenue within metrics. | `100` | | `data.report.metrics.outstandingRevenue` | `number` | Yes | No | outstanding revenue within metrics. | `100` | | `data.report.metrics.expenses` | `number` | Yes | No | expenses within metrics. | `100` | | `data.report.metrics.recurringExpenses` | `number` | Yes | No | recurring expenses within metrics. | `100` | | `data.report.metrics.payouts` | `number` | Yes | No | payouts within metrics. | `100` | | `data.report.metrics.paidPayouts` | `number` | Yes | No | paid payouts within metrics. | `100` | | `data.report.metrics.pendingPayouts` | `number` | Yes | No | pending payouts within metrics. | `100` | | `data.report.metrics.netIncome` | `number` | Yes | No | net income within metrics. | `100` | | `data.report.metrics.cashOnHand` | `number` | Yes | No | cash on hand within metrics. | `100` | | `data.report.outputVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.report.inputVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.report.vatBalance` | `number` | Yes | No | vat balance within report. | `100` | | `data.report.vatPaid` | `number` | Yes | No | vat paid within report. | `100` | | `data.report.vatOpeningBalance` | `number` | Yes | No | vat opening balance within report. | `100` | | `data.report.taxExpense` | `number` | Yes | No | tax expense within report. | `100` | | `data.report.ebt` | `number` | Yes | No | ebt within report. | `100` | | `data.report.netCashFlow` | `number` | Yes | No | net cash flow within report. | `100` | | `data.report.payables` | `object[]` | Yes | No | payables within report. | — | | `data.report.payables[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.payables[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.payables[].modifierId` | `string` | Yes | No | ID of the related modifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.report.payables[].purpose` | `string` | Yes | No | purpose within payables. (Allowed values: "custom", "vat", "zakah") | `"custom"` | | `data.report.payables[].recipient` | `string` | Yes | No | recipient within payables. | `"Product sale"` | | `data.report.payables[].modifierName` | `string` | Yes | No | modifier name within payables. | `"Product sale"` | | `data.report.payables[].opening` | `number` | Yes | No | opening within payables. | `100` | | `data.report.payables[].accrued` | `number` | Yes | No | accrued within payables. | `100` | | `data.report.payables[].paid` | `number` | Yes | No | paid within payables. | `100` | | `data.report.payables[].remaining` | `number` | Yes | No | remaining within payables. | `0` | | `data.report.payables[].vat` | `object` | No | Yes | Value-added tax amount. | — | | `data.report.payables[].vat.output` | `number` | Yes | No | output within vat. | `100` | | `data.report.payables[].vat.input` | `number` | Yes | No | input within vat. | `100` | | `data.filters` | `object` | Yes | No | filters for this report. | — | | `data.filters.start` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.filters.end` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "report": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "metrics": { "revenue": 100, "paidRevenue": 100, "outstandingRevenue": 100, "expenses": 100, "recurringExpenses": 100, "payouts": 100, "paidPayouts": 100, "pendingPayouts": 100, "netIncome": 100, "cashOnHand": 100 }, "outputVat": 100, "inputVat": 100, "vatBalance": 100, "vatPaid": 100, "vatOpeningBalance": 100, "taxExpense": 100, "ebt": 100, "netCashFlow": 100, "payables": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "purpose": "custom", "recipient": "Product sale", "modifierName": "Product sale", "opening": 100, "accrued": 100, "paid": 100, "remaining": 0 } ] }, "filters": {}, "fiscalStart": "2026-01-01", "defaultRange": { "end": "2026-01-31", "start": "2026-01-01" }, "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Product sale"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/income-statement" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/income-statement", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/income-statement failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List workspace financial movements **GET** `/v1/reports/movements` List workspace financial movements. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/movements](https://docs.nqd.app/v1/reference/reports/movements) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `direction` | `string` | No | No | Optional direction filter or query option. (Allowed values: "inbound", "outbound") | `"inbound"` | | `page` | `string` | No | No | One-based page number for this resource directory. (pattern ^[+-]?\\d*\\.?\\d+(?:[Ee][+-]?\\d+)?$) | `"25"` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.reportingCurrency` | `string` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | `"Consulting services"` | | `data.totals` | `object` | Yes | No | totals for this report. | — | | `data.totals.inbound` | `string` | Yes | Yes | inbound within totals. | `"100.00"` | | `data.totals.outbound` | `string` | Yes | Yes | outbound within totals. | `"100.00"` | | `data.totals.net` | `string` | Yes | Yes | Total before tax and other modifiers. | `"100.00"` | | `data.totals.missingConversion` | `boolean` | Yes | No | missing conversion within totals. | `true` | | `data.rows` | `object[]` | Yes | No | rows for this report. | — | | `data.rows[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.rows[].sourceId` | `string` | Yes | No | ID of the related source. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.rows[].source` | `object` | Yes | Yes | source within rows. | — | | `data.rows[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.rows[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data.rows[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data.rows[].reportingAmount` | `string` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data.rows[].direction` | `string` | Yes | No | direction within rows. (Allowed values: "inbound", "outbound") | `"inbound"` | | `data.rows[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.rows[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.rows[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.rows[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.rows[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.rows[].account` | `string` | Yes | Yes | account within rows. | `"Operating account"` | | `data.rows[].context` | `object` | Yes | No | context within rows. | — | | `data.rows[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data.rows[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data.rows[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data.rows[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | ```json { "data": { "reportingCurrency": "Consulting services", "totals": { "inbound": "100.00", "outbound": "100.00", "net": "100.00", "missingConversion": true }, "rows": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "sourceId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "type": "invoice" }, "amount": "100.00", "reportingAmount": "100.00", "direction": "inbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "account": "Operating account", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "createdAt": "2026-01-15T12:00:00.000Z" } ], "hasMore": false } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/movements?start=2026-01-15&end=2026-01-15" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/movements", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); url.searchParams.append("start", "2026-01-15"); url.searchParams.append("end", "2026-01-15"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/movements failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read the workspace financial overview report **GET** `/v1/reports/overview` Return the reports overview. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/overview](https://docs.nqd.app/v1/reference/reports/overview) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.period` | `object` | Yes | No | period for this report. | — | | `data.period.startLabel` | `string` | No | Yes | start label within period. | `"Consulting services"` | | `data.period.endLabel` | `string` | No | Yes | end label within period. | `"Consulting services"` | | `data.period.isAllTime` | `boolean` | Yes | No | is all time within period. | `true` | | `data.period.startDate` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.period.endDate` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.overview` | `object` | Yes | No | overview for this report. | — | | `data.overview.invoices` | `object` | Yes | No | invoices within overview. | — | | `data.overview.invoices.pending` | `object` | Yes | No | pending within invoices. | — | | `data.overview.invoices.pending.count` | `number` | Yes | No | count within pending. | `100` | | `data.overview.invoices.pending.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.pending.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.pending.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.draft` | `object` | Yes | No | draft within invoices. | — | | `data.overview.invoices.draft.count` | `number` | Yes | No | count within draft. | `100` | | `data.overview.invoices.draft.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.draft.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.draft.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.paid` | `object` | Yes | No | paid within invoices. | — | | `data.overview.invoices.paid.count` | `number` | Yes | No | count within paid. | `100` | | `data.overview.invoices.paid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.paid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.paid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.overpaid` | `object` | Yes | No | overpaid within invoices. | — | | `data.overview.invoices.overpaid.count` | `number` | Yes | No | count within overpaid. | `100` | | `data.overview.invoices.overpaid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.overpaid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.overpaid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.cancelled` | `object` | Yes | No | cancelled within invoices. | — | | `data.overview.invoices.cancelled.count` | `number` | Yes | No | count within cancelled. | `100` | | `data.overview.invoices.cancelled.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.cancelled.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.cancelled.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.totalCount` | `number` | Yes | No | total count within invoices. | `100` | | `data.overview.invoices.totalNet` | `number` | Yes | No | total net within invoices. | `100` | | `data.overview.invoices.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.totalGross` | `number` | Yes | No | total gross within invoices. | `100` | | `data.overview.recognized` | `object` | Yes | No | recognized within overview. | — | | `data.overview.recognized.count` | `number` | Yes | No | count within recognized. | `100` | | `data.overview.recognized.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.recognized.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.recognized.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.standaloneIncome` | `object` | Yes | No | standalone income within overview. | — | | `data.overview.standaloneIncome.count` | `number` | Yes | No | count within standalone income. | `100` | | `data.overview.standaloneIncome.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts` | `object` | Yes | No | payouts within overview. | — | | `data.overview.payouts.pending` | `object` | Yes | No | pending within payouts. | — | | `data.overview.payouts.pending.count` | `number` | Yes | No | count within pending. | `100` | | `data.overview.payouts.pending.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.pending.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.pending.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.draft` | `object` | Yes | No | draft within payouts. | — | | `data.overview.payouts.draft.count` | `number` | Yes | No | count within draft. | `100` | | `data.overview.payouts.draft.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.draft.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.draft.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.paid` | `object` | Yes | No | paid within payouts. | — | | `data.overview.payouts.paid.count` | `number` | Yes | No | count within paid. | `100` | | `data.overview.payouts.paid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.paid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.paid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.overpaid` | `object` | Yes | No | overpaid within payouts. | — | | `data.overview.payouts.overpaid.count` | `number` | Yes | No | count within overpaid. | `100` | | `data.overview.payouts.overpaid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.overpaid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.overpaid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.cancelled` | `object` | Yes | No | cancelled within payouts. | — | | `data.overview.payouts.cancelled.count` | `number` | Yes | No | count within cancelled. | `100` | | `data.overview.payouts.cancelled.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.cancelled.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.cancelled.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.totalCount` | `number` | Yes | No | total count within payouts. | `100` | | `data.overview.payouts.totalNet` | `number` | Yes | No | total net within payouts. | `100` | | `data.overview.payouts.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.totalGross` | `number` | Yes | No | total gross within payouts. | `100` | | `data.overview.expenses` | `object` | Yes | No | expenses within overview. | — | | `data.overview.expenses.count` | `number` | Yes | No | count within expenses. | `100` | | `data.overview.expenses.totalNet` | `number` | Yes | No | total net within expenses. | `100` | | `data.overview.expenses.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.totalGross` | `number` | Yes | No | total gross within expenses. | `100` | | `data.overview.expenses.operatingNet` | `number` | Yes | No | operating net within expenses. | `100` | | `data.overview.expenses.operatingVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.operatingGross` | `number` | Yes | No | operating gross within expenses. | `100` | | `data.overview.expenses.recurringExpenseNet` | `number` | Yes | No | recurring expense net within expenses. | `100` | | `data.overview.expenses.recurringExpenseVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.recurringExpenseGross` | `number` | Yes | No | recurring expense gross within expenses. | `100` | | `data.overview.expenses.taxPaymentNet` | `number` | Yes | No | tax payment net within expenses. | `100` | | `data.overview.expenses.taxPaymentVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.taxPaymentGross` | `number` | Yes | No | tax payment gross within expenses. | `100` | | `data.overview.recurringExpenses` | `object` | Yes | No | recurring expenses within overview. | — | | `data.overview.recurringExpenses.activeCount` | `number` | Yes | No | active count within recurring expenses. | `100` | | `data.overview.recurringExpenses.monthlyNet` | `number` | Yes | No | monthly net within recurring expenses. | `100` | | `data.overview.recurringExpenses.monthlyVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.recurringExpenses.monthlyGross` | `number` | Yes | No | monthly gross within recurring expenses. | `100` | | `data.overview.recurringExpenses.annualNet` | `number` | Yes | No | annual net within recurring expenses. | `100` | | `data.overview.recurringExpenses.annualVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.recurringExpenses.annualGross` | `number` | Yes | No | annual gross within recurring expenses. | `100` | | `data.overview.profit` | `object` | Yes | No | profit within overview. | — | | `data.overview.profit.salesNet` | `number` | Yes | No | sales net within profit. | `100` | | `data.overview.profit.directCostNet` | `number` | Yes | No | direct cost net within profit. | `100` | | `data.overview.profit.grossProfit` | `number` | Yes | No | gross profit within profit. | `100` | | `data.overview.profit.operatingExpenseNet` | `number` | Yes | No | operating expense net within profit. | `100` | | `data.overview.profit.operatingProfit` | `number` | Yes | No | operating profit within profit. | `100` | | `data.overview.profit.operatingMargin` | `number` | Yes | Yes | operating margin within profit. | `100` | | `data.overview.vat` | `object` | Yes | No | Value-added tax amount. | — | | `data.overview.vat.output` | `number` | Yes | No | output within vat. | `100` | | `data.overview.vat.inputFromDirectCosts` | `number` | Yes | No | input from direct costs within vat. | `100` | | `data.overview.vat.inputFromOperatingExpenses` | `number` | Yes | No | input from operating expenses within vat. | `100` | | `data.overview.vat.beforeRecordedPayments` | `number` | Yes | No | before recorded payments within vat. | `100` | | `data.overview.vat.recordedPayments` | `number` | Yes | No | recorded payments within vat. | `100` | | `data.overview.vat.remaining` | `number` | Yes | No | remaining within vat. | `0` | | `data.overview.cash` | `object` | Yes | No | cash within overview. | — | | `data.overview.cash.collected` | `number` | Yes | No | collected within cash. | `100` | | `data.overview.cash.outflow` | `number` | Yes | No | outflow within cash. | `100` | | `data.overview.cash.directCostsPaid` | `number` | Yes | No | direct costs paid within cash. | `100` | | `data.overview.cash.expensesPaid` | `number` | Yes | No | expenses paid within cash. | `100` | | `data.overview.cash.beforeRemainingVat` | `number` | Yes | No | Value-added tax amount. | `0` | | `data.overview.cash.afterRemainingVat` | `number` | Yes | No | Value-added tax amount. | `0` | | `data.overview.openItems` | `object` | Yes | No | open items within overview. | — | | `data.overview.openItems.receivable` | `number` | Yes | No | receivable within open items. | `100` | | `data.overview.openItems.payable` | `number` | Yes | No | Amount due after all applied modifiers. | `100` | | `data.overview.openItems.netIfOpenItemsClear` | `number` | Yes | No | net if open items clear within open items. | `100` | | `data.overview.openItems.collectionModifier` | `number` | Yes | Yes | collection modifier within open items. | `100` | | `data.overview.dataQuality` | `object` | Yes | No | data quality within overview. | — | | `data.overview.dataQuality.invoicesWithoutValueEntries` | `number` | Yes | No | invoices without value entries within data quality. | `100` | | `data.overview.dataQuality.invoicesWithMissingModifiers` | `number` | Yes | No | invoices with missing modifiers within data quality. | `100` | | `data.overview.dataQuality.payoutsWithMissingModifiers` | `number` | Yes | No | payouts with missing modifiers within data quality. | `100` | | `data.overview.dataQuality.expensesWithMissingModifiers` | `number` | Yes | No | expenses with missing modifiers within data quality. | `100` | | `data.overview.dataQuality.unconvertibleInvoices` | `number` | Yes | No | unconvertible invoices within data quality. | `100` | | `data.overview.dataQuality.unconvertiblePayouts` | `number` | Yes | No | unconvertible payouts within data quality. | `100` | | `data.overview.dataQuality.unconvertibleExpenses` | `number` | Yes | No | unconvertible expenses within data quality. | `100` | | `data.overview.topClients` | `object[]` | Yes | No | top clients within overview. | — | | `data.overview.topClients[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.overview.topClients[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topClients[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topClients[].subtitle` | `string` | No | Yes | subtitle within top clients. | `"Consulting services"` | | `data.overview.topProjects` | `object[]` | Yes | No | top projects within overview. | — | | `data.overview.topProjects[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.overview.topProjects[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topProjects[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topProjects[].subtitle` | `string` | No | Yes | subtitle within top projects. | `"Consulting services"` | | `data.overview.topVendors` | `object[]` | Yes | No | top vendors within overview. | — | | `data.overview.topVendors[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.overview.topVendors[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topVendors[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topVendors[].subtitle` | `string` | No | Yes | subtitle within top vendors. | `"Consulting services"` | | `data.overview.topPayoutContacts` | `object[]` | Yes | No | top payout contacts within overview. | — | | `data.overview.topPayoutContacts[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.overview.topPayoutContacts[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topPayoutContacts[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topPayoutContacts[].subtitle` | `string` | No | Yes | subtitle within top payout contacts. | `"Consulting services"` | | `data.overview.trend` | `object[]` | Yes | No | trend within overview. | — | | `data.overview.trend[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.overview.trend[].salesNet` | `number` | Yes | No | sales net within trend. | `100` | | `data.overview.trend[].directCostNet` | `number` | Yes | No | direct cost net within trend. | `100` | | `data.overview.trend[].operatingExpenseNet` | `number` | Yes | No | operating expense net within trend. | `100` | | `data.overview.trend[].profit` | `number` | Yes | No | profit within trend. | `100` | | `data.overview.trend[].cashIn` | `number` | Yes | No | cash in within trend. | `100` | | `data.overview.trend[].cashOut` | `number` | Yes | No | cash out within trend. | `100` | | `data.overview.history` | `object[]` | Yes | No | history within overview. | — | | `data.overview.history[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.overview.history[].salesNet` | `number` | Yes | No | sales net within history. | `100` | | `data.overview.history[].directCostNet` | `number` | Yes | No | direct cost net within history. | `100` | | `data.overview.history[].operatingExpenseNet` | `number` | Yes | No | operating expense net within history. | `100` | | `data.overview.history[].profit` | `number` | Yes | No | profit within history. | `100` | | `data.overview.history[].cashIn` | `number` | Yes | No | cash in within history. | `100` | | `data.overview.history[].cashOut` | `number` | Yes | No | cash out within history. | `100` | | `data.overview.filingChecks` | `object[]` | Yes | No | filing checks within overview. | — | | `data.overview.filingChecks[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.overview.filingChecks[].state` | `string` | Yes | No | Current state of the record or operation. (Allowed values: "good", "warn", "bad") | `"good"` | | `data.overview.filingChecks[].count` | `number` | No | Yes | count within filing checks. | `100` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "period": { "isAllTime": true }, "defaultRange": { "start": "2026-01-01", "end": "2026-01-31" }, "overview": { "invoices": { "pending": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "draft": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "paid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "overpaid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "cancelled": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "totalCount": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100 }, "recognized": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "standaloneIncome": { "count": 100, "net": 100 }, "payouts": { "pending": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "draft": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "paid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "overpaid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "cancelled": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "totalCount": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100 }, "expenses": { "count": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100, "operatingNet": 100, "operatingVat": 100, "operatingGross": 100, "recurringExpenseNet": 100, "recurringExpenseVat": 100, "recurringExpenseGross": 100, "taxPaymentNet": 100, "taxPaymentVat": 100, "taxPaymentGross": 100 }, "recurringExpenses": { "activeCount": 100, "monthlyNet": 100, "monthlyVat": 100, "monthlyGross": 100, "annualNet": 100, "annualVat": 100, "annualGross": 100 }, "profit": { "salesNet": 100, "directCostNet": 100, "grossProfit": 100, "operatingExpenseNet": 100, "operatingProfit": 100, "operatingMargin": 100 }, "vat": { "output": 100, "inputFromDirectCosts": 100, "inputFromOperatingExpenses": 100, "beforeRecordedPayments": 100, "recordedPayments": 100, "remaining": 0 }, "cash": { "collected": 100, "outflow": 100, "directCostsPaid": 100, "expensesPaid": 100, "beforeRemainingVat": 0, "afterRemainingVat": 0 }, "openItems": { "receivable": 100, "payable": 100, "netIfOpenItemsClear": 100, "collectionModifier": 100 }, "dataQuality": { "invoicesWithoutValueEntries": 100, "invoicesWithMissingModifiers": 100, "payoutsWithMissingModifiers": 100, "expensesWithMissingModifiers": 100, "unconvertibleInvoices": 100, "unconvertiblePayouts": 100, "unconvertibleExpenses": 100 }, "topClients": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "amount": 100 } ], "topProjects": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "name": "NQD record", "amount": 100 } ], "topVendors": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "amount": 100 } ], "topPayoutContacts": [ { "id": "Consulting services", "name": "NQD record", "amount": 100 } ], "trend": [ { "date": "Consulting services", "salesNet": 100, "directCostNet": 100, "operatingExpenseNet": 100, "profit": 100, "cashIn": 100, "cashOut": 100 } ], "history": [ { "date": "Consulting services", "salesNet": 100, "directCostNet": 100, "operatingExpenseNet": 100, "profit": 100, "cashIn": 100, "cashOut": 100 } ], "filingChecks": [ { "id": "Consulting services", "state": "good" } ] }, "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/overview" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/overview", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/overview failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read workspace payables aging **GET** `/v1/reports/payables` Read open expense, payout, and asset purchase balances as of end. Aging uses source dates, with credits and advances shown separately; it does not identify overdue payments. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/payables](https://docs.nqd.app/v1/reference/reports/payables) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.totalOpen` | `number` | Yes | No | total open for this report. | `100` | | `data.totalCredits` | `number` | Yes | No | total credits for this report. | `100` | | `data.totalAdvances` | `number` | Yes | No | total advances for this report. | `100` | | `data.parties` | `object[]` | Yes | No | parties for this report. | — | | `data.parties[].id` | `string` | Yes | Yes | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.parties[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.parties[].href` | `string` | Yes | Yes | href within parties. | `"Consulting services"` | | `data.parties[].open` | `number` | Yes | No | open within parties. | `100` | | `data.parties[].credit` | `number` | Yes | No | credit within parties. | `100` | | `data.parties[].advance` | `number` | Yes | No | advance within parties. | `100` | | `data.parties[].rowCount` | `number` | Yes | No | row count within parties. | `1` | | `data.buckets` | `object[]` | Yes | No | buckets for this report. | — | | `data.buckets[].bucket` | `string` | Yes | No | bucket within buckets. (Allowed values: "0_30", "31_60", "61_90", "91_plus") | `"0_30"` | | `data.buckets[].open` | `number` | Yes | No | open within buckets. | `100` | | `data.buckets[].rowCount` | `number` | Yes | No | row count within buckets. | `1` | | `data.rows` | `object[]` | Yes | No | rows for this report. | — | | `data.rows[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.rows[].sourceType` | `string` | Yes | No | source type within rows. (Allowed values: "expense", "payout", "asset") | `"expense"` | | `data.rows[].partyId` | `string` | Yes | Yes | ID of the related party. | `"Consulting services"` | | `data.rows[].partyName` | `string` | Yes | No | party name within rows. | `"Consulting services"` | | `data.rows[].originalAmount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.rows[].reportingAmount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.rows[].paid` | `number` | Yes | No | paid within rows. | `100` | | `data.rows[].open` | `number` | Yes | No | open within rows. | `100` | | `data.rows[].ageDays` | `number` | Yes | No | age days within rows. | `100` | | `data.rows[].bucket` | `string` | Yes | Yes | bucket within rows. (Allowed values: "0_30", "31_60", "61_90", "91_plus") | `"0_30"` | | `data.rows[].negativeKind` | `string` | Yes | Yes | negative kind within rows. (Allowed values: "credit", "advance") | `"credit"` | | `data.rows[].currency` | `string` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | `"Consulting services"` | | `data.rows[].partyHref` | `string` | Yes | Yes | party href within rows. | `"Consulting services"` | | `data.rows[].reportingCurrency` | `string` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | `"Consulting services"` | | `data.rows[].href` | `string` | Yes | No | href within rows. | `"Consulting services"` | | `data.rows[].sourceDate` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.filters` | `object` | Yes | No | filters for this report. | — | | `data.filters.start` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.filters.end` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.filters.clients` | `string[]` | No | Yes | clients within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `data.filters.projects` | `string[]` | No | Yes | projects within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `data.filters.vendors` | `string[]` | No | Yes | vendors within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `data.filters.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.filters.invoices` | `string[]` | No | Yes | invoices within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `data.filters.expenses` | `string[]` | No | Yes | expenses within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `data.filters.recurringExpenses` | `string[]` | No | Yes | recurring expenses within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `data.filters.payouts` | `string[]` | No | Yes | payouts within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.asOfDate` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "totalOpen": 100, "totalCredits": 100, "totalAdvances": 100, "parties": [ { "id": "Consulting services", "name": "NQD record", "href": "Consulting services", "open": 100, "credit": 100, "advance": 100, "rowCount": 1 } ], "buckets": [ { "bucket": "0_30", "open": 100, "rowCount": 1 } ], "rows": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "sourceType": "expense", "partyId": "Consulting services", "partyName": "Consulting services", "originalAmount": 100, "reportingAmount": 100, "paid": 100, "open": 100, "ageDays": 100, "bucket": "0_30", "negativeKind": "credit", "currency": "Consulting services", "partyHref": "Consulting services", "reportingCurrency": "Consulting services", "href": "Consulting services", "sourceDate": "Consulting services" } ], "filters": {}, "fiscalStart": "2026-01-01", "defaultRange": { "start": "2026-01-01", "end": "2026-01-31" }, "asOfDate": "Consulting services", "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/payables" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/payables", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/payables failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read the workspace profit and loss statement **GET** `/v1/reports/profit-loss` Read the workspace profit and loss statement. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/profit-loss](https://docs.nqd.app/v1/reference/reports/profit-loss) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.profitLoss` | `object` | Yes | No | profit loss for this report. | — | | `data.profitLoss.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.profitLoss.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.profitLoss.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.profitLoss.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.profitLoss.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.profitLoss.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.profitLoss.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.profitLoss.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.profitLoss.rows` | `object[]` | Yes | No | rows within profit loss. | — | | `data.profitLoss.rows[].month` | `string` | Yes | No | month within rows. | `"2026-01"` | | `data.profitLoss.rows[].revenue` | `number` | Yes | No | revenue within rows. | `100` | | `data.profitLoss.rows[].expenses` | `number` | Yes | No | expenses within rows. | `100` | | `data.profitLoss.rows[].net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.profitLoss.standaloneIncome` | `object` | Yes | No | standalone income within profit loss. | — | | `data.profitLoss.standaloneIncome.count` | `number` | Yes | No | count within standalone income. | `100` | | `data.profitLoss.standaloneIncome.recognizedAmount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.profitLoss.consolidated` | `object` | Yes | Yes | consolidated within profit loss. | — | | `data.profitLoss.consolidated.metrics` | `object` | Yes | No | metrics within consolidated. | — | | `data.profitLoss.consolidated.metrics.revenue` | `number` | Yes | No | revenue within metrics. | `100` | | `data.profitLoss.consolidated.metrics.paidRevenue` | `number` | Yes | No | paid revenue within metrics. | `100` | | `data.profitLoss.consolidated.metrics.outstandingRevenue` | `number` | Yes | No | outstanding revenue within metrics. | `100` | | `data.profitLoss.consolidated.metrics.expenses` | `number` | Yes | No | expenses within metrics. | `100` | | `data.profitLoss.consolidated.metrics.recurringExpenses` | `number` | Yes | No | recurring expenses within metrics. | `100` | | `data.profitLoss.consolidated.metrics.payouts` | `number` | Yes | No | payouts within metrics. | `100` | | `data.profitLoss.consolidated.metrics.paidPayouts` | `number` | Yes | No | paid payouts within metrics. | `100` | | `data.profitLoss.consolidated.metrics.pendingPayouts` | `number` | Yes | No | pending payouts within metrics. | `100` | | `data.profitLoss.consolidated.metrics.netIncome` | `number` | Yes | No | net income within metrics. | `100` | | `data.profitLoss.consolidated.metrics.cashOnHand` | `number` | Yes | No | cash on hand within metrics. | `100` | | `data.profitLoss.consolidated.recognizedTaxInflow` | `number` | Yes | No | recognized tax inflow within consolidated. | `100` | | `data.profitLoss.consolidated.recognizedTaxOutflow` | `number` | Yes | No | recognized tax outflow within consolidated. | `100` | | `data.profitLoss.consolidated.capitalizedCost` | `number` | Yes | No | capitalized cost within consolidated. | `100` | | `data.profitLoss.consolidated.assetCarryingValue` | `number` | Yes | No | asset carrying value within consolidated. | `100` | | `data.profitLoss.consolidated.committedResult` | `number` | Yes | No | committed result within consolidated. | `100` | | `data.profitLoss.consolidated.cashResult` | `number` | Yes | No | cash result within consolidated. | `100` | | `data.profitLoss.consolidated.netIncomeBeforeTax` | `number` | Yes | No | net income before tax within consolidated. | `100` | | `data.profitLoss.consolidated.netIncomeAfterTax` | `number` | Yes | No | net income after tax within consolidated. | `100` | | `data.filters` | `object` | Yes | No | filters for this report. | — | | `data.filters.start` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.filters.end` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "profitLoss": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "rows": [ { "month": "2026-01", "revenue": 100, "expenses": 100, "net": 100 } ], "standaloneIncome": { "count": 100, "recognizedAmount": 100 }, "consolidated": { "metrics": { "revenue": 100, "paidRevenue": 100, "outstandingRevenue": 100, "expenses": 100, "recurringExpenses": 100, "payouts": 100, "paidPayouts": 100, "pendingPayouts": 100, "netIncome": 100, "cashOnHand": 100 }, "recognizedTaxInflow": 100, "recognizedTaxOutflow": 100, "capitalizedCost": 100, "assetCarryingValue": 100, "committedResult": 100, "cashResult": 100, "netIncomeBeforeTax": 100, "netIncomeAfterTax": 100 } }, "filters": {}, "fiscalStart": "2026-01-01", "defaultRange": { "end": "2026-01-31", "start": "2026-01-01" }, "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/profit-loss" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/profit-loss", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/profit-loss failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read workspace receivables aging **GET** `/v1/reports/receivables` Read open invoice and standalone income balances as of end. Age by explicit due date or source date, separating unknown due dates, customer credits, and advances. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/receivables](https://docs.nqd.app/v1/reference/reports/receivables) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `basis` | `string` | No | No | Optional basis filter or query option. (Allowed values: "due_date", "source_date") | `"due_date"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `contacts` | `string[]` | No | No | Optional contacts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1E"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.basis` | `string` | Yes | No | basis for this report. (Allowed values: "due_date", "source_date") | `"due_date"` | | `data.totalAmount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.totalPaid` | `number` | Yes | No | total paid for this report. | `100` | | `data.totalReceivable` | `number` | Yes | No | total receivable for this report. | `100` | | `data.totalCredits` | `number` | Yes | No | total credits for this report. | `100` | | `data.totalAdvances` | `number` | Yes | No | total advances for this report. | `100` | | `data.parties` | `object[]` | Yes | No | parties for this report. | — | | `data.parties[].id` | `string` | Yes | Yes | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.parties[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.parties[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.parties[].paid` | `number` | Yes | No | paid within parties. | `100` | | `data.parties[].remaining` | `number` | Yes | No | remaining within parties. | `0` | | `data.parties[].credit` | `number` | Yes | No | credit within parties. | `100` | | `data.parties[].advance` | `number` | Yes | No | advance within parties. | `100` | | `data.parties[].rowCount` | `number` | Yes | No | row count within parties. | `1` | | `data.buckets` | `object[]` | Yes | No | buckets for this report. | — | | `data.buckets[].bucket` | `string` | Yes | No | bucket within buckets. (Allowed values: "current", "1_30", "31_60", "61_90", "91_plus", "no_due_date", "customer_credit", "customer_advance") | `"current"` | | `data.buckets[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.buckets[].paid` | `number` | Yes | No | paid within buckets. | `100` | | `data.buckets[].remaining` | `number` | Yes | No | remaining within buckets. | `0` | | `data.buckets[].rowCount` | `number` | Yes | No | row count within buckets. | `1` | | `data.rows` | `object[]` | Yes | No | rows for this report. | — | | `data.rows[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.rows[].sourceType` | `string` | Yes | No | source type within rows. (Allowed values: "invoice", "income") | `"invoice"` | | `data.rows[].partyId` | `string` | Yes | Yes | ID of the related party. | `"Consulting services"` | | `data.rows[].partyName` | `string` | Yes | No | party name within rows. | `"Consulting services"` | | `data.rows[].projectId` | `string` | Yes | Yes | Project identifier within the current workspace. | `null` | | `data.rows[].projectName` | `string` | Yes | Yes | project name within rows. | `"Consulting project"` | | `data.rows[].contactId` | `string` | Yes | Yes | Contact identifier for the invoice, expense, income, or project contact in the current workspace. | `null` | | `data.rows[].contactName` | `string` | Yes | Yes | contact name within rows. | `"NQD contact"` | | `data.rows[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.rows[].paid` | `number` | Yes | No | paid within rows. | `100` | | `data.rows[].remaining` | `number` | Yes | No | remaining within rows. | `0` | | `data.rows[].ageDays` | `number` | Yes | Yes | age days within rows. | `100` | | `data.rows[].bucket` | `string` | Yes | No | bucket within rows. (Allowed values: "current", "1_30", "31_60", "61_90", "91_plus", "no_due_date", "customer_credit", "customer_advance") | `"current"` | | `data.rows[].currency` | `string` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | `"Consulting services"` | | `data.rows[].sourceDate` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.rows[].dueDate` | `string` | Yes | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.filters` | `object` | Yes | No | filters for this report. | — | | `data.filters.start` | `string` | Yes | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.filters.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.start` | `string` | Yes | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.asOfDate` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "basis": "due_date", "totalAmount": 100, "totalPaid": 100, "totalReceivable": 100, "totalCredits": 100, "totalAdvances": 100, "parties": [ { "id": "Consulting services", "name": "NQD record", "amount": 100, "paid": 100, "remaining": 0, "credit": 100, "advance": 100, "rowCount": 1 } ], "buckets": [ { "bucket": "current", "amount": 100, "paid": 100, "remaining": 0, "rowCount": 1 } ], "rows": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "sourceType": "invoice", "partyId": "Consulting services", "partyName": "Consulting services", "projectId": null, "projectName": "Consulting project", "contactId": null, "contactName": "NQD contact", "amount": 100, "paid": 100, "remaining": 0, "ageDays": 100, "bucket": "current", "currency": "Consulting services", "sourceDate": "Consulting services", "dueDate": "Consulting services" } ], "fiscalStart": "2026-01-01", "filters": { "start": "2026-01-01", "end": "2026-01-31" }, "defaultRange": { "start": "2026-01-01", "end": "2026-01-31" }, "asOfDate": "Consulting services", "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/receivables" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/receivables", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/receivables failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read workspace financial statements **GET** `/v1/reports/statements` Read workspace financial statements. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/statements](https://docs.nqd.app/v1/reference/reports/statements) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.report` | `object` | Yes | No | report for this report. | — | | `data.report.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.report.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.report.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.report.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.report.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.report.metrics` | `object` | Yes | No | metrics within report. | — | | `data.report.metrics.revenue` | `number` | Yes | No | revenue within metrics. | `100` | | `data.report.metrics.paidRevenue` | `number` | Yes | No | paid revenue within metrics. | `100` | | `data.report.metrics.outstandingRevenue` | `number` | Yes | No | outstanding revenue within metrics. | `100` | | `data.report.metrics.expenses` | `number` | Yes | No | expenses within metrics. | `100` | | `data.report.metrics.recurringExpenses` | `number` | Yes | No | recurring expenses within metrics. | `100` | | `data.report.metrics.payouts` | `number` | Yes | No | payouts within metrics. | `100` | | `data.report.metrics.paidPayouts` | `number` | Yes | No | paid payouts within metrics. | `100` | | `data.report.metrics.pendingPayouts` | `number` | Yes | No | pending payouts within metrics. | `100` | | `data.report.metrics.netIncome` | `number` | Yes | No | net income within metrics. | `100` | | `data.report.metrics.cashOnHand` | `number` | Yes | No | cash on hand within metrics. | `100` | | `data.report.collectionModifier` | `number` | Yes | Yes | collection modifier within report. | `100` | | `data.report.expensePayable` | `number` | Yes | No | expense payable within report. | `100` | | `data.report.inputVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.report.outputVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.report.netVatPosition` | `number` | Yes | No | net vat position within report. | `100` | | `data.report.vatPaid` | `number` | Yes | No | vat paid within report. | `100` | | `data.report.standaloneIncome` | `object` | Yes | No | standalone income within report. | — | | `data.report.standaloneIncome.count` | `number` | Yes | No | count within standalone income. | `100` | | `data.report.standaloneIncome.recognizedAmount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.report.consolidated` | `object` | Yes | Yes | consolidated within report. | — | | `data.report.consolidated.metrics` | `object` | Yes | No | metrics within consolidated. | — | | `data.report.consolidated.metrics.revenue` | `number` | Yes | No | revenue within metrics. | `100` | | `data.report.consolidated.metrics.paidRevenue` | `number` | Yes | No | paid revenue within metrics. | `100` | | `data.report.consolidated.metrics.outstandingRevenue` | `number` | Yes | No | outstanding revenue within metrics. | `100` | | `data.report.consolidated.metrics.expenses` | `number` | Yes | No | expenses within metrics. | `100` | | `data.report.consolidated.metrics.recurringExpenses` | `number` | Yes | No | recurring expenses within metrics. | `100` | | `data.report.consolidated.metrics.payouts` | `number` | Yes | No | payouts within metrics. | `100` | | `data.report.consolidated.metrics.paidPayouts` | `number` | Yes | No | paid payouts within metrics. | `100` | | `data.report.consolidated.metrics.pendingPayouts` | `number` | Yes | No | pending payouts within metrics. | `100` | | `data.report.consolidated.metrics.netIncome` | `number` | Yes | No | net income within metrics. | `100` | | `data.report.consolidated.metrics.cashOnHand` | `number` | Yes | No | cash on hand within metrics. | `100` | | `data.report.consolidated.recognizedTaxInflow` | `number` | Yes | No | recognized tax inflow within consolidated. | `100` | | `data.report.consolidated.recognizedTaxOutflow` | `number` | Yes | No | recognized tax outflow within consolidated. | `100` | | `data.report.consolidated.capitalizedCost` | `number` | Yes | No | capitalized cost within consolidated. | `100` | | `data.report.consolidated.assetCarryingValue` | `number` | Yes | No | asset carrying value within consolidated. | `100` | | `data.report.consolidated.committedResult` | `number` | Yes | No | committed result within consolidated. | `100` | | `data.report.consolidated.cashResult` | `number` | Yes | No | cash result within consolidated. | `100` | | `data.report.consolidated.netIncomeBeforeTax` | `number` | Yes | No | net income before tax within consolidated. | `100` | | `data.report.consolidated.netIncomeAfterTax` | `number` | Yes | No | net income after tax within consolidated. | `100` | | `data.report.profitLoss` | `object` | Yes | No | profit loss within report. | — | | `data.report.profitLoss.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.report.profitLoss.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.report.profitLoss.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.profitLoss.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.report.profitLoss.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.profitLoss.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.profitLoss.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.report.profitLoss.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.report.profitLoss.buckets` | `string[]` | Yes | No | buckets within profit loss. | `["Consulting services"]` | | `data.report.profitLoss.rows` | `object[]` | Yes | No | rows within profit loss. | — | | `data.report.profitLoss.rows[].month` | `string` | Yes | No | month within rows. | `"2026-01"` | | `data.report.profitLoss.rows[].revenue` | `number` | Yes | No | revenue within rows. | `100` | | `data.report.profitLoss.rows[].expenses` | `number` | Yes | No | expenses within rows. | `100` | | `data.report.profitLoss.rows[].net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.report.profitLoss.granularity` | `string` | Yes | No | granularity within profit loss. (Allowed values: "day", "month", "year") | `"day"` | | `data.report.topClients` | `object[]` | Yes | No | top clients within report. | — | | `data.report.topClients[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.topClients[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.topClients[].total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.report.topProjects` | `object[]` | Yes | No | top projects within report. | — | | `data.report.topProjects[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.report.topProjects[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.topProjects[].total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.report.topInvoices` | `object[]` | Yes | No | top invoices within report. | — | | `data.report.topInvoices[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.report.topInvoices[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.topInvoices[].count` | `number` | Yes | No | count within top invoices. | `100` | | `data.report.topVendors` | `object[]` | Yes | No | top vendors within report. | — | | `data.report.topVendors[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.topVendors[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.topVendors[].total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.report.topExpenses` | `object[]` | Yes | No | top expenses within report. | — | | `data.report.topExpenses[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data.report.topExpenses[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.topExpenses[].total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.report.topRecurringExpenses` | `object[]` | Yes | No | top recurring expenses within report. | — | | `data.report.topRecurringExpenses[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `data.report.topRecurringExpenses[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.topRecurringExpenses[].total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.report.topPayouts` | `object[]` | Yes | No | top payouts within report. | — | | `data.report.topPayouts[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data.report.topPayouts[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.topPayouts[].total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.report.payoutFutureIntents` | `object[]` | Yes | No | payout future intents within report. | — | | `data.report.payoutFutureIntents[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.report.payoutFutureIntents[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data.report.payoutFutureIntents[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.report.payoutFutureIntents[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.report.payoutFutureIntents[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.payoutFutureIntents[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.report.payoutFutureIntents[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.payoutFutureIntents[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.payoutFutureIntents[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.report.payoutFutureIntents[].nextOccurrenceAt` | `string` | Yes | Yes | ISO 8601 timestamp for next occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.report.selectedFilters` | `object` | Yes | No | selected filters within report. | — | | `data.report.selectedFilters.clients` | `object[]` | Yes | No | clients within selected filters. | — | | `data.report.selectedFilters.clients[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.selectedFilters.clients[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.selectedFilters.projects` | `object[]` | Yes | No | projects within selected filters. | — | | `data.report.selectedFilters.projects[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.report.selectedFilters.projects[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.report.selectedFilters.vendors` | `object[]` | Yes | No | vendors within selected filters. | — | | `data.report.selectedFilters.vendors[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.report.selectedFilters.vendors[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.selectedFilters.tags` | `object[]` | Yes | No | Tags assigned to the record. | — | | `data.report.selectedFilters.tags[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | | `data.report.selectedFilters.tags[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.selectedFilters.invoices` | `object[]` | Yes | No | invoices within selected filters. | — | | `data.report.selectedFilters.invoices[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1P"` | | `data.report.selectedFilters.invoices[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.report.selectedFilters.expenses` | `object[]` | Yes | No | expenses within selected filters. | — | | `data.report.selectedFilters.expenses[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1R"` | | `data.report.selectedFilters.expenses[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.report.selectedFilters.recurringExpenses` | `object[]` | Yes | No | recurring expenses within selected filters. | — | | `data.report.selectedFilters.recurringExpenses[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1S"` | | `data.report.selectedFilters.recurringExpenses[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.report.selectedFilters.payouts` | `object[]` | Yes | No | payouts within selected filters. | — | | `data.report.selectedFilters.payouts[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1T"` | | `data.report.selectedFilters.payouts[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.filters` | `object` | Yes | No | filters for this report. | — | | `data.filters.clients` | `string[]` | Yes | No | clients within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `data.filters.projects` | `string[]` | Yes | No | projects within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `data.filters.vendors` | `string[]` | Yes | No | vendors within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `data.filters.tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data.filters.invoices` | `string[]` | Yes | No | invoices within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `data.filters.expenses` | `string[]` | Yes | No | expenses within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `data.filters.recurringExpenses` | `string[]` | Yes | No | recurring expenses within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `data.filters.payouts` | `string[]` | Yes | No | payouts within filters. | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | | `data.filters.start` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.filters.end` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "report": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "metrics": { "revenue": 100, "paidRevenue": 100, "outstandingRevenue": 100, "expenses": 100, "recurringExpenses": 100, "payouts": 100, "paidPayouts": 100, "pendingPayouts": 100, "netIncome": 100, "cashOnHand": 100 }, "collectionModifier": 100, "expensePayable": 100, "inputVat": 100, "outputVat": 100, "netVatPosition": 100, "vatPaid": 100, "standaloneIncome": { "count": 100, "recognizedAmount": 100 }, "consolidated": { "metrics": { "revenue": 100, "paidRevenue": 100, "outstandingRevenue": 100, "expenses": 100, "recurringExpenses": 100, "payouts": 100, "paidPayouts": 100, "pendingPayouts": 100, "netIncome": 100, "cashOnHand": 100 }, "recognizedTaxInflow": 100, "recognizedTaxOutflow": 100, "capitalizedCost": 100, "assetCarryingValue": 100, "committedResult": 100, "cashResult": 100, "netIncomeBeforeTax": 100, "netIncomeAfterTax": 100 }, "profitLoss": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "buckets": [ "Consulting services" ], "rows": [ { "month": "2026-01", "revenue": 100, "expenses": 100, "net": 100 } ], "granularity": "day" }, "topClients": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "total": 100 } ], "topProjects": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "name": "NQD record", "total": 100 } ], "topInvoices": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "name": "NQD record", "count": 100 } ], "topVendors": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "total": 100 } ], "topExpenses": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "name": "NQD record", "total": 100 } ], "topRecurringExpenses": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "name": "NQD record", "total": 100 } ], "topPayouts": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "name": "NQD record", "total": 100 } ], "payoutFutureIntents": [ { "id": "Consulting services", "amount": "100.00", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "nextOccurrenceAt": "2026-01-15T12:00:00.000Z" } ], "selectedFilters": { "clients": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record" } ], "projects": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "name": "NQD record" } ], "vendors": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record" } ], "tags": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M", "name": "NQD record" } ], "invoices": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1P", "name": "NQD record" } ], "expenses": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1R", "name": "NQD record" } ], "recurringExpenses": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1S", "name": "NQD record" } ], "payouts": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1T", "name": "NQD record" } ] } }, "filters": { "clients": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" ], "projects": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1D" ], "vendors": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" ], "tags": [ "equipment" ], "invoices": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1P" ], "expenses": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1R" ], "recurringExpenses": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1S" ], "payouts": [ "01JQ2T5Y5Q3R8W9N6M4K2H7P1T" ] }, "fiscalStart": "2026-01-01", "defaultRange": { "end": "2026-01-31", "start": "2026-01-01" }, "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/statements" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/statements", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/statements failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read the workspace financial summary report **GET** `/v1/reports/summary` Read the workspace financial summary report. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/summary](https://docs.nqd.app/v1/reference/reports/summary) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.cashBalance` | `object` | Yes | Yes | cash balance for this report. | — | | `data.cashBalance.total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.cashBalance.inbound` | `number` | Yes | No | inbound within cash balance. | `100` | | `data.cashBalance.outbound` | `number` | Yes | No | outbound within cash balance. | `100` | | `data.forecast` | `object` | Yes | Yes | forecast for this report. | — | | `data.forecast.unresolved` | `number` | Yes | No | unresolved within forecast. | `100` | | `data.forecast.monthly` | `object[]` | Yes | No | monthly within forecast. | — | | `data.forecast.monthly[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.forecast.monthly[].salesNet` | `number` | Yes | No | sales net within monthly. | `100` | | `data.forecast.baseline` | `number` | Yes | Yes | baseline within forecast. | `100` | | `data.forecast.historyMonths` | `number` | Yes | No | history months within forecast. | `100` | | `data.forecast.model` | `object` | Yes | No | model within forecast. | — | | `data.forecast.model.method` | `string` | Yes | No | method within model. (Allowed values: "mean-3", "mean-6", "last-month", "drift") | `"mean-3"` | | `data.forecast.model.error` | `number` | Yes | Yes | Error details returned for a failed request. | `100` | | `data.forecast.currentMonth` | `object` | Yes | No | current month within forecast. | — | | `data.forecast.currentMonth.date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.forecast.currentMonth.scheduled` | `number` | Yes | No | scheduled within current month. | `100` | | `data.forecast.currentMonth.recurring` | `number` | Yes | No | recurring within current month. | `100` | | `data.forecast.currentMonth.baseline` | `number` | Yes | No | baseline within current month. | `100` | | `data.forecast.currentMonth.actual` | `number` | Yes | No | actual within current month. | `100` | | `data.forecast.currentMonth.remaining` | `number` | Yes | No | remaining within current month. | `0` | | `data.forecast.currentMonth.value` | `number` | Yes | No | Value returned by the operation. | `100` | | `data.forecast.forecast` | `object[]` | Yes | No | forecast within forecast. | — | | `data.forecast.forecast[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.forecast.forecast[].scheduled` | `number` | Yes | No | scheduled within forecast. | `100` | | `data.forecast.forecast[].recurring` | `number` | Yes | No | recurring within forecast. | `100` | | `data.forecast.forecast[].baseline` | `number` | Yes | No | baseline within forecast. | `100` | | `data.forecast.forecast[].actual` | `number` | Yes | No | actual within forecast. | `100` | | `data.forecast.forecast[].remaining` | `number` | Yes | No | remaining within forecast. | `0` | | `data.forecast.forecast[].value` | `number` | Yes | No | Value returned by the operation. | `100` | | `data.forecast.total` | `number` | Yes | No | Total number of records that match the request. | `100` | | `data.today` | `string` | Yes | No | today for this report. | `"Consulting services"` | | `data.burnWindow` | `object` | Yes | No | burn window for this report. | — | | `data.burnWindow.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.burnWindow.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.burnHistory` | `object[]` | Yes | No | burn history for this report. | — | | `data.burnHistory[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.burnHistory[].cashIn` | `number` | Yes | No | cash in within burn history. | `100` | | `data.burnHistory[].cashOut` | `number` | Yes | No | cash out within burn history. | `100` | | `data.previous` | `object` | Yes | Yes | previous for this report. | — | | `data.previous.invoices` | `object` | Yes | No | invoices within previous. | — | | `data.previous.invoices.pending` | `object` | Yes | No | pending within invoices. | — | | `data.previous.invoices.pending.count` | `number` | Yes | No | count within pending. | `100` | | `data.previous.invoices.pending.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.invoices.pending.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.invoices.pending.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.invoices.draft` | `object` | Yes | No | draft within invoices. | — | | `data.previous.invoices.draft.count` | `number` | Yes | No | count within draft. | `100` | | `data.previous.invoices.draft.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.invoices.draft.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.invoices.draft.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.invoices.paid` | `object` | Yes | No | paid within invoices. | — | | `data.previous.invoices.paid.count` | `number` | Yes | No | count within paid. | `100` | | `data.previous.invoices.paid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.invoices.paid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.invoices.paid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.invoices.overpaid` | `object` | Yes | No | overpaid within invoices. | — | | `data.previous.invoices.overpaid.count` | `number` | Yes | No | count within overpaid. | `100` | | `data.previous.invoices.overpaid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.invoices.overpaid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.invoices.overpaid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.invoices.cancelled` | `object` | Yes | No | cancelled within invoices. | — | | `data.previous.invoices.cancelled.count` | `number` | Yes | No | count within cancelled. | `100` | | `data.previous.invoices.cancelled.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.invoices.cancelled.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.invoices.cancelled.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.invoices.totalCount` | `number` | Yes | No | total count within invoices. | `100` | | `data.previous.invoices.totalNet` | `number` | Yes | No | total net within invoices. | `100` | | `data.previous.invoices.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.invoices.totalGross` | `number` | Yes | No | total gross within invoices. | `100` | | `data.previous.recognized` | `object` | Yes | No | recognized within previous. | — | | `data.previous.recognized.count` | `number` | Yes | No | count within recognized. | `100` | | `data.previous.recognized.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.recognized.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.recognized.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.standaloneIncome` | `object` | Yes | No | standalone income within previous. | — | | `data.previous.standaloneIncome.count` | `number` | Yes | No | count within standalone income. | `100` | | `data.previous.standaloneIncome.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.payouts` | `object` | Yes | No | payouts within previous. | — | | `data.previous.payouts.pending` | `object` | Yes | No | pending within payouts. | — | | `data.previous.payouts.pending.count` | `number` | Yes | No | count within pending. | `100` | | `data.previous.payouts.pending.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.payouts.pending.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.payouts.pending.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.payouts.draft` | `object` | Yes | No | draft within payouts. | — | | `data.previous.payouts.draft.count` | `number` | Yes | No | count within draft. | `100` | | `data.previous.payouts.draft.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.payouts.draft.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.payouts.draft.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.payouts.paid` | `object` | Yes | No | paid within payouts. | — | | `data.previous.payouts.paid.count` | `number` | Yes | No | count within paid. | `100` | | `data.previous.payouts.paid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.payouts.paid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.payouts.paid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.payouts.overpaid` | `object` | Yes | No | overpaid within payouts. | — | | `data.previous.payouts.overpaid.count` | `number` | Yes | No | count within overpaid. | `100` | | `data.previous.payouts.overpaid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.payouts.overpaid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.payouts.overpaid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.payouts.cancelled` | `object` | Yes | No | cancelled within payouts. | — | | `data.previous.payouts.cancelled.count` | `number` | Yes | No | count within cancelled. | `100` | | `data.previous.payouts.cancelled.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.previous.payouts.cancelled.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.payouts.cancelled.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.previous.payouts.totalCount` | `number` | Yes | No | total count within payouts. | `100` | | `data.previous.payouts.totalNet` | `number` | Yes | No | total net within payouts. | `100` | | `data.previous.payouts.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.payouts.totalGross` | `number` | Yes | No | total gross within payouts. | `100` | | `data.previous.expenses` | `object` | Yes | No | expenses within previous. | — | | `data.previous.expenses.count` | `number` | Yes | No | count within expenses. | `100` | | `data.previous.expenses.totalNet` | `number` | Yes | No | total net within expenses. | `100` | | `data.previous.expenses.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.expenses.totalGross` | `number` | Yes | No | total gross within expenses. | `100` | | `data.previous.expenses.operatingNet` | `number` | Yes | No | operating net within expenses. | `100` | | `data.previous.expenses.operatingVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.expenses.operatingGross` | `number` | Yes | No | operating gross within expenses. | `100` | | `data.previous.expenses.recurringExpenseNet` | `number` | Yes | No | recurring expense net within expenses. | `100` | | `data.previous.expenses.recurringExpenseVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.expenses.recurringExpenseGross` | `number` | Yes | No | recurring expense gross within expenses. | `100` | | `data.previous.expenses.taxPaymentNet` | `number` | Yes | No | tax payment net within expenses. | `100` | | `data.previous.expenses.taxPaymentVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.expenses.taxPaymentGross` | `number` | Yes | No | tax payment gross within expenses. | `100` | | `data.previous.recurringExpenses` | `object` | Yes | No | recurring expenses within previous. | — | | `data.previous.recurringExpenses.activeCount` | `number` | Yes | No | active count within recurring expenses. | `100` | | `data.previous.recurringExpenses.monthlyNet` | `number` | Yes | No | monthly net within recurring expenses. | `100` | | `data.previous.recurringExpenses.monthlyVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.recurringExpenses.monthlyGross` | `number` | Yes | No | monthly gross within recurring expenses. | `100` | | `data.previous.recurringExpenses.annualNet` | `number` | Yes | No | annual net within recurring expenses. | `100` | | `data.previous.recurringExpenses.annualVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.previous.recurringExpenses.annualGross` | `number` | Yes | No | annual gross within recurring expenses. | `100` | | `data.previous.profit` | `object` | Yes | No | profit within previous. | — | | `data.previous.profit.salesNet` | `number` | Yes | No | sales net within profit. | `100` | | `data.previous.profit.directCostNet` | `number` | Yes | No | direct cost net within profit. | `100` | | `data.previous.profit.grossProfit` | `number` | Yes | No | gross profit within profit. | `100` | | `data.previous.profit.operatingExpenseNet` | `number` | Yes | No | operating expense net within profit. | `100` | | `data.previous.profit.operatingProfit` | `number` | Yes | No | operating profit within profit. | `100` | | `data.previous.profit.operatingMargin` | `number` | Yes | Yes | operating margin within profit. | `100` | | `data.previous.vat` | `object` | Yes | No | Value-added tax amount. | — | | `data.previous.vat.output` | `number` | Yes | No | output within vat. | `100` | | `data.previous.vat.inputFromDirectCosts` | `number` | Yes | No | input from direct costs within vat. | `100` | | `data.previous.vat.inputFromOperatingExpenses` | `number` | Yes | No | input from operating expenses within vat. | `100` | | `data.previous.vat.beforeRecordedPayments` | `number` | Yes | No | before recorded payments within vat. | `100` | | `data.previous.vat.recordedPayments` | `number` | Yes | No | recorded payments within vat. | `100` | | `data.previous.vat.remaining` | `number` | Yes | No | remaining within vat. | `0` | | `data.previous.cash` | `object` | Yes | No | cash within previous. | — | | `data.previous.cash.collected` | `number` | Yes | No | collected within cash. | `100` | | `data.previous.cash.outflow` | `number` | Yes | No | outflow within cash. | `100` | | `data.previous.cash.directCostsPaid` | `number` | Yes | No | direct costs paid within cash. | `100` | | `data.previous.cash.expensesPaid` | `number` | Yes | No | expenses paid within cash. | `100` | | `data.previous.cash.beforeRemainingVat` | `number` | Yes | No | Value-added tax amount. | `0` | | `data.previous.cash.afterRemainingVat` | `number` | Yes | No | Value-added tax amount. | `0` | | `data.previous.openItems` | `object` | Yes | No | open items within previous. | — | | `data.previous.openItems.receivable` | `number` | Yes | No | receivable within open items. | `100` | | `data.previous.openItems.payable` | `number` | Yes | No | Amount due after all applied modifiers. | `100` | | `data.previous.openItems.netIfOpenItemsClear` | `number` | Yes | No | net if open items clear within open items. | `100` | | `data.previous.openItems.collectionModifier` | `number` | Yes | Yes | collection modifier within open items. | `100` | | `data.previous.dataQuality` | `object` | Yes | No | data quality within previous. | — | | `data.previous.dataQuality.invoicesWithoutValueEntries` | `number` | Yes | No | invoices without value entries within data quality. | `100` | | `data.previous.dataQuality.invoicesWithMissingModifiers` | `number` | Yes | No | invoices with missing modifiers within data quality. | `100` | | `data.previous.dataQuality.payoutsWithMissingModifiers` | `number` | Yes | No | payouts with missing modifiers within data quality. | `100` | | `data.previous.dataQuality.expensesWithMissingModifiers` | `number` | Yes | No | expenses with missing modifiers within data quality. | `100` | | `data.previous.dataQuality.unconvertibleInvoices` | `number` | Yes | No | unconvertible invoices within data quality. | `100` | | `data.previous.dataQuality.unconvertiblePayouts` | `number` | Yes | No | unconvertible payouts within data quality. | `100` | | `data.previous.dataQuality.unconvertibleExpenses` | `number` | Yes | No | unconvertible expenses within data quality. | `100` | | `data.previous.topClients` | `object[]` | Yes | No | top clients within previous. | — | | `data.previous.topClients[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.previous.topClients[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.previous.topClients[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.previous.topClients[].subtitle` | `string` | No | Yes | subtitle within top clients. | `"Consulting services"` | | `data.previous.topProjects` | `object[]` | Yes | No | top projects within previous. | — | | `data.previous.topProjects[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.previous.topProjects[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.previous.topProjects[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.previous.topProjects[].subtitle` | `string` | No | Yes | subtitle within top projects. | `"Consulting services"` | | `data.previous.topVendors` | `object[]` | Yes | No | top vendors within previous. | — | | `data.previous.topVendors[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.previous.topVendors[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.previous.topVendors[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.previous.topVendors[].subtitle` | `string` | No | Yes | subtitle within top vendors. | `"Consulting services"` | | `data.previous.topPayoutContacts` | `object[]` | Yes | No | top payout contacts within previous. | — | | `data.previous.topPayoutContacts[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.previous.topPayoutContacts[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.previous.topPayoutContacts[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.previous.topPayoutContacts[].subtitle` | `string` | No | Yes | subtitle within top payout contacts. | `"Consulting services"` | | `data.previous.trend` | `object[]` | Yes | No | trend within previous. | — | | `data.previous.trend[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.previous.trend[].salesNet` | `number` | Yes | No | sales net within trend. | `100` | | `data.previous.trend[].directCostNet` | `number` | Yes | No | direct cost net within trend. | `100` | | `data.previous.trend[].operatingExpenseNet` | `number` | Yes | No | operating expense net within trend. | `100` | | `data.previous.trend[].profit` | `number` | Yes | No | profit within trend. | `100` | | `data.previous.trend[].cashIn` | `number` | Yes | No | cash in within trend. | `100` | | `data.previous.trend[].cashOut` | `number` | Yes | No | cash out within trend. | `100` | | `data.previous.history` | `object[]` | Yes | No | history within previous. | — | | `data.previous.history[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.previous.history[].salesNet` | `number` | Yes | No | sales net within history. | `100` | | `data.previous.history[].directCostNet` | `number` | Yes | No | direct cost net within history. | `100` | | `data.previous.history[].operatingExpenseNet` | `number` | Yes | No | operating expense net within history. | `100` | | `data.previous.history[].profit` | `number` | Yes | No | profit within history. | `100` | | `data.previous.history[].cashIn` | `number` | Yes | No | cash in within history. | `100` | | `data.previous.history[].cashOut` | `number` | Yes | No | cash out within history. | `100` | | `data.previous.filingChecks` | `object[]` | Yes | No | filing checks within previous. | — | | `data.previous.filingChecks[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.previous.filingChecks[].state` | `string` | Yes | No | Current state of the record or operation. (Allowed values: "good", "warn", "bad") | `"good"` | | `data.previous.filingChecks[].count` | `number` | No | Yes | count within filing checks. | `100` | | `data.previousRange` | `object` | Yes | Yes | previous range for this report. | — | | `data.previousRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.previousRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.period` | `object` | Yes | No | period for this report. | — | | `data.period.startLabel` | `string` | No | Yes | start label within period. | `"Consulting services"` | | `data.period.endLabel` | `string` | No | Yes | end label within period. | `"Consulting services"` | | `data.period.isAllTime` | `boolean` | Yes | No | is all time within period. | `true` | | `data.period.startDate` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.period.endDate` | `string` | No | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.overview` | `object` | Yes | No | overview for this report. | — | | `data.overview.invoices` | `object` | Yes | No | invoices within overview. | — | | `data.overview.invoices.pending` | `object` | Yes | No | pending within invoices. | — | | `data.overview.invoices.pending.count` | `number` | Yes | No | count within pending. | `100` | | `data.overview.invoices.pending.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.pending.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.pending.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.draft` | `object` | Yes | No | draft within invoices. | — | | `data.overview.invoices.draft.count` | `number` | Yes | No | count within draft. | `100` | | `data.overview.invoices.draft.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.draft.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.draft.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.paid` | `object` | Yes | No | paid within invoices. | — | | `data.overview.invoices.paid.count` | `number` | Yes | No | count within paid. | `100` | | `data.overview.invoices.paid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.paid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.paid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.overpaid` | `object` | Yes | No | overpaid within invoices. | — | | `data.overview.invoices.overpaid.count` | `number` | Yes | No | count within overpaid. | `100` | | `data.overview.invoices.overpaid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.overpaid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.overpaid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.cancelled` | `object` | Yes | No | cancelled within invoices. | — | | `data.overview.invoices.cancelled.count` | `number` | Yes | No | count within cancelled. | `100` | | `data.overview.invoices.cancelled.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.invoices.cancelled.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.cancelled.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.invoices.totalCount` | `number` | Yes | No | total count within invoices. | `100` | | `data.overview.invoices.totalNet` | `number` | Yes | No | total net within invoices. | `100` | | `data.overview.invoices.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.invoices.totalGross` | `number` | Yes | No | total gross within invoices. | `100` | | `data.overview.recognized` | `object` | Yes | No | recognized within overview. | — | | `data.overview.recognized.count` | `number` | Yes | No | count within recognized. | `100` | | `data.overview.recognized.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.recognized.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.recognized.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.standaloneIncome` | `object` | Yes | No | standalone income within overview. | — | | `data.overview.standaloneIncome.count` | `number` | Yes | No | count within standalone income. | `100` | | `data.overview.standaloneIncome.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts` | `object` | Yes | No | payouts within overview. | — | | `data.overview.payouts.pending` | `object` | Yes | No | pending within payouts. | — | | `data.overview.payouts.pending.count` | `number` | Yes | No | count within pending. | `100` | | `data.overview.payouts.pending.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.pending.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.pending.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.draft` | `object` | Yes | No | draft within payouts. | — | | `data.overview.payouts.draft.count` | `number` | Yes | No | count within draft. | `100` | | `data.overview.payouts.draft.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.draft.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.draft.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.paid` | `object` | Yes | No | paid within payouts. | — | | `data.overview.payouts.paid.count` | `number` | Yes | No | count within paid. | `100` | | `data.overview.payouts.paid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.paid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.paid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.overpaid` | `object` | Yes | No | overpaid within payouts. | — | | `data.overview.payouts.overpaid.count` | `number` | Yes | No | count within overpaid. | `100` | | `data.overview.payouts.overpaid.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.overpaid.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.overpaid.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.cancelled` | `object` | Yes | No | cancelled within payouts. | — | | `data.overview.payouts.cancelled.count` | `number` | Yes | No | count within cancelled. | `100` | | `data.overview.payouts.cancelled.net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.overview.payouts.cancelled.vat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.cancelled.gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.overview.payouts.totalCount` | `number` | Yes | No | total count within payouts. | `100` | | `data.overview.payouts.totalNet` | `number` | Yes | No | total net within payouts. | `100` | | `data.overview.payouts.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.payouts.totalGross` | `number` | Yes | No | total gross within payouts. | `100` | | `data.overview.expenses` | `object` | Yes | No | expenses within overview. | — | | `data.overview.expenses.count` | `number` | Yes | No | count within expenses. | `100` | | `data.overview.expenses.totalNet` | `number` | Yes | No | total net within expenses. | `100` | | `data.overview.expenses.totalVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.totalGross` | `number` | Yes | No | total gross within expenses. | `100` | | `data.overview.expenses.operatingNet` | `number` | Yes | No | operating net within expenses. | `100` | | `data.overview.expenses.operatingVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.operatingGross` | `number` | Yes | No | operating gross within expenses. | `100` | | `data.overview.expenses.recurringExpenseNet` | `number` | Yes | No | recurring expense net within expenses. | `100` | | `data.overview.expenses.recurringExpenseVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.recurringExpenseGross` | `number` | Yes | No | recurring expense gross within expenses. | `100` | | `data.overview.expenses.taxPaymentNet` | `number` | Yes | No | tax payment net within expenses. | `100` | | `data.overview.expenses.taxPaymentVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.expenses.taxPaymentGross` | `number` | Yes | No | tax payment gross within expenses. | `100` | | `data.overview.recurringExpenses` | `object` | Yes | No | recurring expenses within overview. | — | | `data.overview.recurringExpenses.activeCount` | `number` | Yes | No | active count within recurring expenses. | `100` | | `data.overview.recurringExpenses.monthlyNet` | `number` | Yes | No | monthly net within recurring expenses. | `100` | | `data.overview.recurringExpenses.monthlyVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.recurringExpenses.monthlyGross` | `number` | Yes | No | monthly gross within recurring expenses. | `100` | | `data.overview.recurringExpenses.annualNet` | `number` | Yes | No | annual net within recurring expenses. | `100` | | `data.overview.recurringExpenses.annualVat` | `number` | Yes | No | Value-added tax amount. | `100` | | `data.overview.recurringExpenses.annualGross` | `number` | Yes | No | annual gross within recurring expenses. | `100` | | `data.overview.profit` | `object` | Yes | No | profit within overview. | — | | `data.overview.profit.salesNet` | `number` | Yes | No | sales net within profit. | `100` | | `data.overview.profit.directCostNet` | `number` | Yes | No | direct cost net within profit. | `100` | | `data.overview.profit.grossProfit` | `number` | Yes | No | gross profit within profit. | `100` | | `data.overview.profit.operatingExpenseNet` | `number` | Yes | No | operating expense net within profit. | `100` | | `data.overview.profit.operatingProfit` | `number` | Yes | No | operating profit within profit. | `100` | | `data.overview.profit.operatingMargin` | `number` | Yes | Yes | operating margin within profit. | `100` | | `data.overview.vat` | `object` | Yes | No | Value-added tax amount. | — | | `data.overview.vat.output` | `number` | Yes | No | output within vat. | `100` | | `data.overview.vat.inputFromDirectCosts` | `number` | Yes | No | input from direct costs within vat. | `100` | | `data.overview.vat.inputFromOperatingExpenses` | `number` | Yes | No | input from operating expenses within vat. | `100` | | `data.overview.vat.beforeRecordedPayments` | `number` | Yes | No | before recorded payments within vat. | `100` | | `data.overview.vat.recordedPayments` | `number` | Yes | No | recorded payments within vat. | `100` | | `data.overview.vat.remaining` | `number` | Yes | No | remaining within vat. | `0` | | `data.overview.cash` | `object` | Yes | No | cash within overview. | — | | `data.overview.cash.collected` | `number` | Yes | No | collected within cash. | `100` | | `data.overview.cash.outflow` | `number` | Yes | No | outflow within cash. | `100` | | `data.overview.cash.directCostsPaid` | `number` | Yes | No | direct costs paid within cash. | `100` | | `data.overview.cash.expensesPaid` | `number` | Yes | No | expenses paid within cash. | `100` | | `data.overview.cash.beforeRemainingVat` | `number` | Yes | No | Value-added tax amount. | `0` | | `data.overview.cash.afterRemainingVat` | `number` | Yes | No | Value-added tax amount. | `0` | | `data.overview.openItems` | `object` | Yes | No | open items within overview. | — | | `data.overview.openItems.receivable` | `number` | Yes | No | receivable within open items. | `100` | | `data.overview.openItems.payable` | `number` | Yes | No | Amount due after all applied modifiers. | `100` | | `data.overview.openItems.netIfOpenItemsClear` | `number` | Yes | No | net if open items clear within open items. | `100` | | `data.overview.openItems.collectionModifier` | `number` | Yes | Yes | collection modifier within open items. | `100` | | `data.overview.dataQuality` | `object` | Yes | No | data quality within overview. | — | | `data.overview.dataQuality.invoicesWithoutValueEntries` | `number` | Yes | No | invoices without value entries within data quality. | `100` | | `data.overview.dataQuality.invoicesWithMissingModifiers` | `number` | Yes | No | invoices with missing modifiers within data quality. | `100` | | `data.overview.dataQuality.payoutsWithMissingModifiers` | `number` | Yes | No | payouts with missing modifiers within data quality. | `100` | | `data.overview.dataQuality.expensesWithMissingModifiers` | `number` | Yes | No | expenses with missing modifiers within data quality. | `100` | | `data.overview.dataQuality.unconvertibleInvoices` | `number` | Yes | No | unconvertible invoices within data quality. | `100` | | `data.overview.dataQuality.unconvertiblePayouts` | `number` | Yes | No | unconvertible payouts within data quality. | `100` | | `data.overview.dataQuality.unconvertibleExpenses` | `number` | Yes | No | unconvertible expenses within data quality. | `100` | | `data.overview.topClients` | `object[]` | Yes | No | top clients within overview. | — | | `data.overview.topClients[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.overview.topClients[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topClients[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topClients[].subtitle` | `string` | No | Yes | subtitle within top clients. | `"Consulting services"` | | `data.overview.topProjects` | `object[]` | Yes | No | top projects within overview. | — | | `data.overview.topProjects[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1D"` | | `data.overview.topProjects[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topProjects[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topProjects[].subtitle` | `string` | No | Yes | subtitle within top projects. | `"Consulting services"` | | `data.overview.topVendors` | `object[]` | Yes | No | top vendors within overview. | — | | `data.overview.topVendors[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.overview.topVendors[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topVendors[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topVendors[].subtitle` | `string` | No | Yes | subtitle within top vendors. | `"Consulting services"` | | `data.overview.topPayoutContacts` | `object[]` | Yes | No | top payout contacts within overview. | — | | `data.overview.topPayoutContacts[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.overview.topPayoutContacts[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.overview.topPayoutContacts[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.overview.topPayoutContacts[].subtitle` | `string` | No | Yes | subtitle within top payout contacts. | `"Consulting services"` | | `data.overview.trend` | `object[]` | Yes | No | trend within overview. | — | | `data.overview.trend[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.overview.trend[].salesNet` | `number` | Yes | No | sales net within trend. | `100` | | `data.overview.trend[].directCostNet` | `number` | Yes | No | direct cost net within trend. | `100` | | `data.overview.trend[].operatingExpenseNet` | `number` | Yes | No | operating expense net within trend. | `100` | | `data.overview.trend[].profit` | `number` | Yes | No | profit within trend. | `100` | | `data.overview.trend[].cashIn` | `number` | Yes | No | cash in within trend. | `100` | | `data.overview.trend[].cashOut` | `number` | Yes | No | cash out within trend. | `100` | | `data.overview.history` | `object[]` | Yes | No | history within overview. | — | | `data.overview.history[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.overview.history[].salesNet` | `number` | Yes | No | sales net within history. | `100` | | `data.overview.history[].directCostNet` | `number` | Yes | No | direct cost net within history. | `100` | | `data.overview.history[].operatingExpenseNet` | `number` | Yes | No | operating expense net within history. | `100` | | `data.overview.history[].profit` | `number` | Yes | No | profit within history. | `100` | | `data.overview.history[].cashIn` | `number` | Yes | No | cash in within history. | `100` | | `data.overview.history[].cashOut` | `number` | Yes | No | cash out within history. | `100` | | `data.overview.filingChecks` | `object[]` | Yes | No | filing checks within overview. | — | | `data.overview.filingChecks[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.overview.filingChecks[].state` | `string` | Yes | No | Current state of the record or operation. (Allowed values: "good", "warn", "bad") | `"good"` | | `data.overview.filingChecks[].count` | `number` | No | Yes | count within filing checks. | `100` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "cashBalance": { "total": 100, "inbound": 100, "outbound": 100 }, "forecast": { "unresolved": 100, "monthly": [ { "date": "Consulting services", "salesNet": 100 } ], "baseline": 100, "historyMonths": 100, "model": { "method": "mean-3", "error": 100 }, "currentMonth": { "date": "Consulting services", "scheduled": 100, "recurring": 100, "baseline": 100, "actual": 100, "remaining": 0, "value": 100 }, "forecast": [ { "date": "Consulting services", "scheduled": 100, "recurring": 100, "baseline": 100, "actual": 100, "remaining": 0, "value": 100 } ], "total": 100 }, "today": "Consulting services", "burnWindow": { "start": "2026-01-01", "end": "2026-01-31" }, "burnHistory": [ { "date": "Consulting services", "cashIn": 100, "cashOut": 100 } ], "previous": { "invoices": { "pending": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "draft": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "paid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "overpaid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "cancelled": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "totalCount": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100 }, "recognized": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "standaloneIncome": { "count": 100, "net": 100 }, "payouts": { "pending": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "draft": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "paid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "overpaid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "cancelled": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "totalCount": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100 }, "expenses": { "count": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100, "operatingNet": 100, "operatingVat": 100, "operatingGross": 100, "recurringExpenseNet": 100, "recurringExpenseVat": 100, "recurringExpenseGross": 100, "taxPaymentNet": 100, "taxPaymentVat": 100, "taxPaymentGross": 100 }, "recurringExpenses": { "activeCount": 100, "monthlyNet": 100, "monthlyVat": 100, "monthlyGross": 100, "annualNet": 100, "annualVat": 100, "annualGross": 100 }, "profit": { "salesNet": 100, "directCostNet": 100, "grossProfit": 100, "operatingExpenseNet": 100, "operatingProfit": 100, "operatingMargin": 100 }, "vat": { "output": 100, "inputFromDirectCosts": 100, "inputFromOperatingExpenses": 100, "beforeRecordedPayments": 100, "recordedPayments": 100, "remaining": 0 }, "cash": { "collected": 100, "outflow": 100, "directCostsPaid": 100, "expensesPaid": 100, "beforeRemainingVat": 0, "afterRemainingVat": 0 }, "openItems": { "receivable": 100, "payable": 100, "netIfOpenItemsClear": 100, "collectionModifier": 100 }, "dataQuality": { "invoicesWithoutValueEntries": 100, "invoicesWithMissingModifiers": 100, "payoutsWithMissingModifiers": 100, "expensesWithMissingModifiers": 100, "unconvertibleInvoices": 100, "unconvertiblePayouts": 100, "unconvertibleExpenses": 100 }, "topClients": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "amount": 100 } ], "topProjects": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "name": "NQD record", "amount": 100 } ], "topVendors": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "amount": 100 } ], "topPayoutContacts": [ { "id": "Consulting services", "name": "NQD record", "amount": 100 } ], "trend": [ { "date": "Consulting services", "salesNet": 100, "directCostNet": 100, "operatingExpenseNet": 100, "profit": 100, "cashIn": 100, "cashOut": 100 } ], "history": [ { "date": "Consulting services", "salesNet": 100, "directCostNet": 100, "operatingExpenseNet": 100, "profit": 100, "cashIn": 100, "cashOut": 100 } ], "filingChecks": [ { "id": "Consulting services", "state": "good" } ] }, "previousRange": { "start": "2026-01-01", "end": "2026-01-31" }, "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "period": { "isAllTime": true }, "defaultRange": { "start": "2026-01-01", "end": "2026-01-31" }, "overview": { "invoices": { "pending": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "draft": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "paid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "overpaid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "cancelled": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "totalCount": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100 }, "recognized": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "standaloneIncome": { "count": 100, "net": 100 }, "payouts": { "pending": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "draft": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "paid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "overpaid": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "cancelled": { "count": 100, "net": 100, "vat": 100, "gross": 100 }, "totalCount": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100 }, "expenses": { "count": 100, "totalNet": 100, "totalVat": 100, "totalGross": 100, "operatingNet": 100, "operatingVat": 100, "operatingGross": 100, "recurringExpenseNet": 100, "recurringExpenseVat": 100, "recurringExpenseGross": 100, "taxPaymentNet": 100, "taxPaymentVat": 100, "taxPaymentGross": 100 }, "recurringExpenses": { "activeCount": 100, "monthlyNet": 100, "monthlyVat": 100, "monthlyGross": 100, "annualNet": 100, "annualVat": 100, "annualGross": 100 }, "profit": { "salesNet": 100, "directCostNet": 100, "grossProfit": 100, "operatingExpenseNet": 100, "operatingProfit": 100, "operatingMargin": 100 }, "vat": { "output": 100, "inputFromDirectCosts": 100, "inputFromOperatingExpenses": 100, "beforeRecordedPayments": 100, "recordedPayments": 100, "remaining": 0 }, "cash": { "collected": 100, "outflow": 100, "directCostsPaid": 100, "expensesPaid": 100, "beforeRemainingVat": 0, "afterRemainingVat": 0 }, "openItems": { "receivable": 100, "payable": 100, "netIfOpenItemsClear": 100, "collectionModifier": 100 }, "dataQuality": { "invoicesWithoutValueEntries": 100, "invoicesWithMissingModifiers": 100, "payoutsWithMissingModifiers": 100, "expensesWithMissingModifiers": 100, "unconvertibleInvoices": 100, "unconvertiblePayouts": 100, "unconvertibleExpenses": 100 }, "topClients": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "amount": 100 } ], "topProjects": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1D", "name": "NQD record", "amount": 100 } ], "topVendors": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "amount": 100 } ], "topPayoutContacts": [ { "id": "Consulting services", "name": "NQD record", "amount": 100 } ], "trend": [ { "date": "Consulting services", "salesNet": 100, "directCostNet": 100, "operatingExpenseNet": 100, "profit": 100, "cashIn": 100, "cashOut": 100 } ], "history": [ { "date": "Consulting services", "salesNet": 100, "directCostNet": 100, "operatingExpenseNet": 100, "profit": 100, "cashIn": 100, "cashOut": 100 } ], "filingChecks": [ { "id": "Consulting services", "state": "good" } ] }, "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/summary" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/summary", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/summary failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read workspace tax control **GET** `/v1/reports/tax-control` Read recorded source output and input tax, effective remittances and refunds, and opening-to-closing control balances for start through end. This is not a statutory tax return. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/tax-control](https://docs.nqd.app/v1/reference/reports/tax-control) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.period` | `object` | Yes | No | period for this report. | — | | `data.period.start` | `string` | Yes | Yes | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-01"` | | `data.period.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-31"` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.filters` | `object` | Yes | No | filters for this report. | — | | `data.filters.start` | `string` | Yes | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.filters.end` | `string` | Yes | Yes | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.opening` | `number` | Yes | No | opening for this report. | `100` | | `data.output` | `number` | Yes | No | output for this report. | `100` | | `data.input` | `number` | Yes | No | input for this report. | `100` | | `data.payments` | `number` | Yes | No | payments for this report. | `100` | | `data.adjustments` | `number` | Yes | No | adjustments for this report. | `100` | | `data.closing` | `number` | Yes | No | closing for this report. | `100` | | `data.sources` | `object[]` | Yes | No | sources for this report. | — | | `data.sources[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.sources[].sourceKind` | `string` | Yes | No | source kind within sources. (Allowed values: "invoice", "income", "expense", "payout", "asset") | `"invoice"` | | `data.sources[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.sources[].context` | `string` | Yes | Yes | context within sources. | `"Consulting services"` | | `data.sources[].net` | `number` | Yes | No | Total before tax and other modifiers. | `100` | | `data.sources[].tax` | `number` | Yes | No | Tax calculated from the workspace payable modifier. | `100` | | `data.sources[].gross` | `number` | Yes | No | Total after tax and other price modifiers. | `100` | | `data.sources[].currency` | `string` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | `"Consulting services"` | | `data.sources[].link` | `string` | Yes | No | link within sources. | `"Consulting services"` | | `data.sources[].taxDirection` | `string` | Yes | No | tax direction within sources. (Allowed values: "output", "input") | `"output"` | | `data.sources[].sourceDate` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.paymentRows` | `object[]` | Yes | No | payment rows for this report. | — | | `data.paymentRows[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.paymentRows[].sourceId` | `string` | Yes | Yes | ID of the related source. | `null` | | `data.paymentRows[].date` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.paymentRows[].amount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.paymentRows[].nativeAmount` | `number` | Yes | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.paymentRows[].nativeCurrency` | `string` | Yes | Yes | native currency within payment rows. | `"Consulting services"` | | `data.paymentRows[].direction` | `string` | Yes | No | direction within payment rows. (Allowed values: "payment", "refund") | `"payment"` | | `data.paymentRows[].link` | `string` | Yes | Yes | link within payment rows. | `"Consulting services"` | | `data.payableCards` | `object[]` | Yes | No | payable cards for this report. | — | | `data.payableCards[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"Consulting services"` | | `data.payableCards[].vendorId` | `string` | Yes | No | ID of the related vendor. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.payableCards[].modifierId` | `string` | Yes | No | ID of the related modifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1J"` | | `data.payableCards[].purpose` | `string` | Yes | No | purpose within payable cards. (Allowed values: "custom", "vat", "zakah") | `"custom"` | | `data.payableCards[].recipient` | `string` | Yes | No | recipient within payable cards. | `"Consulting services"` | | `data.payableCards[].modifierName` | `string` | Yes | No | modifier name within payable cards. | `"Consulting services"` | | `data.payableCards[].opening` | `number` | Yes | No | opening within payable cards. | `100` | | `data.payableCards[].accrued` | `number` | Yes | No | accrued within payable cards. | `100` | | `data.payableCards[].paid` | `number` | Yes | No | paid within payable cards. | `100` | | `data.payableCards[].remaining` | `number` | Yes | No | remaining within payable cards. | `0` | | `data.payableCards[].vat` | `object` | No | Yes | Value-added tax amount. | — | | `data.payableCards[].vat.output` | `number` | Yes | No | output within vat. | `100` | | `data.payableCards[].vat.input` | `number` | Yes | No | input within vat. | `100` | | `data.recordedFactsOnly` | `boolean` | Yes | No | recorded facts only for this report. (Allowed values: true) | `true` | | `data.limitations` | `string[]` | Yes | No | limitations for this report. | `["Consulting services"]` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "period": { "start": "2026-01-01", "end": "2026-01-31" }, "fiscalStart": "2026-01-01", "filters": { "start": "2026-01-01", "end": "2026-01-31" }, "opening": 100, "output": 100, "input": 100, "payments": 100, "adjustments": 100, "closing": 100, "sources": [ { "id": "Consulting services", "sourceKind": "invoice", "name": "NQD record", "context": "Consulting services", "net": 100, "tax": 100, "gross": 100, "currency": "Consulting services", "link": "Consulting services", "taxDirection": "output", "sourceDate": "Consulting services" } ], "paymentRows": [ { "id": "Consulting services", "sourceId": null, "date": "Consulting services", "amount": 100, "nativeAmount": 100, "nativeCurrency": "Consulting services", "direction": "payment", "link": "Consulting services" } ], "payableCards": [ { "id": "Consulting services", "vendorId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "modifierId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1J", "purpose": "custom", "recipient": "Consulting services", "modifierName": "Consulting services", "opening": 100, "accrued": 100, "paid": 100, "remaining": 0 } ], "recordedFactsOnly": true, "limitations": [ "Consulting services" ], "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/tax-control" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/tax-control", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/tax-control failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read the workspace trial balance **GET** `/v1/reports/trial-balance` Read the workspace trial balance. - Canonical URL: [https://docs.nqd.app/v1/reference/reports/trial-balance](https://docs.nqd.app/v1/reference/reports/trial-balance) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `bankAccountId` | `string` | No | No | Optional bank account id filter or query option. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1G"` | | `start` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `end` | `string` | No | No | Calendar date in YYYY-MM-DD format for the reporting period. (Maximum length: 10 characters.) | `"2026-01-15"` | | `range` | `string` | No | No | Optional range filter or query option. (Allowed values: "all") | `"all"` | | `timezone` | `string` | No | No | Optional timezone filter or query option. (Maximum length: 100 characters.) | `"UTC"` | | `clients` | `string[]` | No | No | Optional clients filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `projects` | `string[]` | No | No | Optional projects filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1D"]` | | `vendors` | `string[]` | No | No | Optional vendors filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1C"]` | | `tags` | `string[]` | No | No | Optional tags filter or query option. (at most 500 items) | `["equipment"]` | | `invoices` | `string[]` | No | No | Optional invoices filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1P"]` | | `expenses` | `string[]` | No | No | Optional expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1R"]` | | `recurringExpenses` | `string[]` | No | No | Optional recurring expenses filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1S"]` | | `payouts` | `string[]` | No | No | Optional payouts filter or query option. (at most 500 items) | `["01JQ2T5Y5Q3R8W9N6M4K2H7P1T"]` | ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.report` | `object` | Yes | No | report for this report. | — | | `data.report.currency` | `object` | Yes | Yes | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data.report.currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data.report.currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data.report.currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data.report.currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data.report.currency.name` | `string` | Yes | No | Display name of the record. | `"Saudi Riyal"` | | `data.report.accounts` | `object[]` | Yes | No | accounts within report. | — | | `data.report.accounts[].key` | `string` | Yes | No | key within accounts. | `"Consulting services"` | | `data.report.accounts[].label` | `string` | Yes | No | Human-readable label for the value. | `"Operating account"` | | `data.report.accounts[].type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "asset", "liability", "equity", "income", "expense", "unresolved") | `"asset"` | | `data.report.accounts[].status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "resolved", "unresolved") | `"resolved"` | | `data.report.accounts[].debit` | `number` | Yes | No | debit within accounts. | `100` | | `data.report.accounts[].credit` | `number` | Yes | No | credit within accounts. | `100` | | `data.report.accounts[].context` | `string` | No | Yes | context within accounts. | `"Consulting services"` | | `data.report.totalDebit` | `number` | Yes | No | total debit within report. | `100` | | `data.report.totalCredit` | `number` | Yes | No | total credit within report. | `100` | | `data.report.difference` | `number` | Yes | No | difference within report. | `100` | | `data.report.unresolvedCount` | `number` | Yes | No | unresolved count within report. | `100` | | `data.report.unresolvedAmount` | `number` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `100` | | `data.fiscalStart` | `string` | Yes | Yes | fiscal start for this report. | `"2026-01-01"` | | `data.defaultRange` | `object` | Yes | No | default range for this report. | — | | `data.defaultRange.end` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-31"` | | `data.defaultRange.start` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"2026-01-01"` | | `data.asOfDate` | `string` | Yes | No | Calendar date in YYYY-MM-DD format for the reporting period. | `"Consulting services"` | | `data.generatedAt` | `string` | Yes | No | ISO 8601 timestamp for generated. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "report": { "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" }, "name": "Saudi Riyal" }, "accounts": [ { "key": "Consulting services", "label": "Operating account", "type": "asset", "status": "resolved", "debit": 100, "credit": 100 } ], "totalDebit": 100, "totalCredit": 100, "difference": 100, "unresolvedCount": 100, "unresolvedAmount": 100 }, "fiscalStart": "2026-01-01", "defaultRange": { "end": "2026-01-31", "start": "2026-01-01" }, "asOfDate": "Consulting services", "generatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/reports/trial-balance" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/reports/trial-balance", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/reports/trial-balance failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Get integration retention **GET** `/v1/retention` Read the workspace integration log and webhook delivery retention policy. - Canonical URL: [https://docs.nqd.app/v1/reference/retention/retrieve](https://docs.nqd.app/v1/reference/retention/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.enabled` | `boolean` | Yes | No | Whether this option is enabled. | `true` | | `data.logRetentionDays` | `number` | Yes | Yes | log retention days for this retention. (minimum 1, maximum 3650) | `1` | | `data.deliveryRetentionDays` | `number` | Yes | Yes | delivery retention days for this retention. (minimum 1, maximum 3650) | `1` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "enabled": true, "logRetentionDays": 1, "deliveryRetentionDays": 1, "updatedBy": null, "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/retention" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/retention", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/retention failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Update integration retention **PUT** `/v1/retention` Update workspace retention windows. Null keeps that record type forever; cleanup stays disabled until enabled. - Canonical URL: [https://docs.nqd.app/v1/reference/retention/upsert](https://docs.nqd.app/v1/reference/retention/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `enabled` | `boolean` | Yes | No | Whether this option is enabled. | `true` | | `logRetentionDays` | `number` | Yes | Yes | log retention days for this retention. (minimum 1, maximum 3650) | `1` | | `deliveryRetentionDays` | `number` | Yes | Yes | delivery retention days for this retention. (minimum 1, maximum 3650) | `1` | ```json { "enabled": true, "logRetentionDays": 1, "deliveryRetentionDays": 1 } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.enabled` | `boolean` | Yes | No | Whether this option is enabled. | `true` | | `data.logRetentionDays` | `number` | Yes | Yes | log retention days for this retention. (minimum 1, maximum 3650) | `1` | | `data.deliveryRetentionDays` | `number` | Yes | Yes | delivery retention days for this retention. (minimum 1, maximum 3650) | `1` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "enabled": true, "logRetentionDays": 1, "deliveryRetentionDays": 1, "updatedBy": null, "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/retention" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "enabled": true, "logRetentionDays": 1, "deliveryRetentionDays": 1 }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/retention", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "enabled": true, "logRetentionDays": 1, "deliveryRetentionDays": 1 }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/retention failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Preview integration retention **GET** `/v1/retention/preview` Preview eligible and protected integration logs and webhook deliveries for this workspace. - Canonical URL: [https://docs.nqd.app/v1/reference/retention/preview/retrieve](https://docs.nqd.app/v1/reference/retention/preview/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.policy` | `object` | Yes | No | policy for this retention. | — | | `data.policy.enabled` | `boolean` | Yes | No | Whether this option is enabled. | `true` | | `data.policy.logRetentionDays` | `number` | Yes | Yes | log retention days within policy. (minimum 1, maximum 3650) | `1` | | `data.policy.deliveryRetentionDays` | `number` | Yes | Yes | delivery retention days within policy. (minimum 1, maximum 3650) | `1` | | `data.policy.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. (Minimum length: 1 character., Maximum length: 128 characters.) | `null` | | `data.policy.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.policyRevision` | `string` | Yes | No | policy revision for this retention. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.deliveryCandidates` | `number` | Yes | No | delivery candidates for this retention. | `100` | | `data.logCandidates` | `number` | Yes | No | log candidates for this retention. | `100` | | `data.protectedDeliveries` | `number` | Yes | No | protected deliveries for this retention. | `100` | | `data.protectedLogs` | `number` | Yes | No | protected logs for this retention. | `100` | | `data.protectedReasons` | `object[]` | Yes | No | protected reasons for this retention. | — | | `data.protectedReasons[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. | `"Consulting services"` | | `data.protectedReasons[].count` | `number` | Yes | No | count within protected reasons. | `1` | | `data.oldestDeliveryCandidateAt` | `string` | Yes | Yes | ISO 8601 timestamp for oldest delivery candidate. | `"2026-01-15T12:00:00.000Z"` | | `data.oldestLogCandidateAt` | `string` | Yes | Yes | ISO 8601 timestamp for oldest log candidate. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "policy": { "enabled": true, "logRetentionDays": 1, "deliveryRetentionDays": 1, "updatedBy": null, "updatedAt": "2026-01-15T12:00:00.000Z" }, "policyRevision": "Consulting services", "deliveryCandidates": 100, "logCandidates": 100, "protectedDeliveries": 100, "protectedLogs": 100, "protectedReasons": [ { "reason": "Consulting services", "count": 1 } ], "oldestDeliveryCandidateAt": "2026-01-15T12:00:00.000Z", "oldestLogCandidateAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/retention/preview" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/retention/preview", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/retention/preview failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Prune integration retention **POST** `/v1/retention/prune` Explicitly prune eligible integration logs and webhook deliveries for this workspace after preview confirmation. - Canonical URL: [https://docs.nqd.app/v1/reference/retention/prune/create](https://docs.nqd.app/v1/reference/retention/prune/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `policyRevision` | `string` | Yes | No | policy revision for this retention. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `maxRows` | `number` | No | Yes | max rows for this retention. (maximum 1000, greater than 0) | `100` | | `confirm` | `value` | Yes | No | confirm for this retention. | `"prune"` | ```json { "policyRevision": "Consulting services", "confirm": "prune" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.policyRevision` | `string` | Yes | No | policy revision for this retention. (Minimum length: 1 character., Maximum length: 128 characters.) | `"Consulting services"` | | `data.deletedDeliveries` | `number` | Yes | No | deleted deliveries for this retention. | `100` | | `data.deletedLogs` | `number` | Yes | No | deleted logs for this retention. | `100` | | `data.protectedDeliveries` | `number` | Yes | No | protected deliveries for this retention. | `100` | | `data.protectedLogs` | `number` | Yes | No | protected logs for this retention. | `100` | | `data.complete` | `boolean` | Yes | No | complete for this retention. | `true` | ```json { "data": { "policyRevision": "Consulting services", "deletedDeliveries": 100, "deletedLogs": 100, "protectedDeliveries": 100, "protectedLogs": 100, "complete": true } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/retention/prune" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "policyRevision": "Consulting services", "confirm": "prune" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/retention/prune", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "policyRevision": "Consulting services", "confirm": "prune" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/retention/prune failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Read workspace settings **GET** `/v1/settings` Read workspace settings. - Canonical URL: [https://docs.nqd.app/v1/reference/settings/retrieve](https://docs.nqd.app/v1/reference/settings/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Acme workspace"` | | `data.slug` | `string` | Yes | No | slug for this setting. | `"acme-workspace"` | | `data.officialName` | `string` | Yes | Yes | official name for this setting. | `"Consulting services"` | | `data.tradeName` | `string` | Yes | Yes | trade name for this setting. | `"Consulting services"` | | `data.registrationNumber` | `string` | Yes | Yes | registration number for this setting. | `"CR-0001234567"` | | `data.taxId` | `string` | Yes | Yes | ID of the related tax. | `"100.00"` | | `data.defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. | `null` | | `data.defaultInvoiceBankAccountId` | `string` | Yes | Yes | ID of the related default invoice bank account. | `null` | | `data.defaultIncomeBankAccountId` | `string` | Yes | Yes | ID of the related default income bank account. | `null` | | `data.defaultAssetBankAccountId` | `string` | Yes | Yes | ID of the related default asset bank account. | `null` | | `data.defaultExpenseBankAccountId` | `string` | Yes | Yes | ID of the related default expense bank account. | `null` | | `data.defaultPayoutBankAccountId` | `string` | Yes | Yes | ID of the related default payout bank account. | `null` | | `data.defaultExpenseRecurringBankAccountId` | `string` | Yes | Yes | ID of the related default expense recurring bank account. | `null` | | `data.email` | `string` | Yes | Yes | Email address associated with the identity. | `"owner@example.com"` | | `data.phone` | `string` | Yes | Yes | phone for this setting. | `"+966500000000"` | | `data.address` | `string` | Yes | Yes | address for this setting. | `"King Fahd Road"` | | `data.city` | `string` | Yes | Yes | city for this setting. | `"Riyadh"` | | `data.state` | `string` | Yes | Yes | Current state of the record or operation. | `"Riyadh"` | | `data.postalCode` | `string` | Yes | Yes | postal code for this setting. | `"Consulting services"` | | `data.country` | `string` | Yes | Yes | country for this setting. | `"SA"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this setting. | `null` | | `data.fiscalYearStartAt` | `string` | Yes | Yes | ISO 8601 timestamp for fiscal year start. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1A", "name": "Acme workspace", "slug": "acme-workspace", "officialName": "Consulting services", "tradeName": "Consulting services", "registrationNumber": "CR-0001234567", "taxId": "100.00", "defaultCurrencyId": null, "defaultInvoiceBankAccountId": null, "defaultIncomeBankAccountId": null, "defaultAssetBankAccountId": null, "defaultExpenseBankAccountId": null, "defaultPayoutBankAccountId": null, "defaultExpenseRecurringBankAccountId": null, "email": "owner@example.com", "phone": "+966500000000", "address": "King Fahd Road", "city": "Riyadh", "state": "Riyadh", "postalCode": "Consulting services", "country": "SA", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "fiscalYearStartAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/settings" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/settings", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/settings failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Update workspace settings **PUT** `/v1/settings` Update workspace settings. - Canonical URL: [https://docs.nqd.app/v1/reference/settings/upsert](https://docs.nqd.app/v1/reference/settings/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `field` | `string` | Yes | No | field for this setting. (Allowed values: "name", "slug", "officialName", "tradeName", "registrationNumber", "taxId", "email", "phone", "address", "city", "state", "zip", "country") | `"name"` | | `value` | `string` | Yes | No | Value returned by the operation. (Maximum length: 2048 characters.) | `"100.00"` | ```json { "field": "name", "value": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"Acme workspace"` | | `data.slug` | `string` | Yes | No | slug for this setting. | `"acme-workspace"` | | `data.officialName` | `string` | Yes | Yes | official name for this setting. | `"Consulting services"` | | `data.tradeName` | `string` | Yes | Yes | trade name for this setting. | `"Consulting services"` | | `data.registrationNumber` | `string` | Yes | Yes | registration number for this setting. | `"CR-0001234567"` | | `data.taxId` | `string` | Yes | Yes | ID of the related tax. | `"100.00"` | | `data.defaultCurrencyId` | `string` | Yes | Yes | ID of the related default currency. | `null` | | `data.defaultInvoiceBankAccountId` | `string` | Yes | Yes | ID of the related default invoice bank account. | `null` | | `data.defaultIncomeBankAccountId` | `string` | Yes | Yes | ID of the related default income bank account. | `null` | | `data.defaultAssetBankAccountId` | `string` | Yes | Yes | ID of the related default asset bank account. | `null` | | `data.defaultExpenseBankAccountId` | `string` | Yes | Yes | ID of the related default expense bank account. | `null` | | `data.defaultPayoutBankAccountId` | `string` | Yes | Yes | ID of the related default payout bank account. | `null` | | `data.defaultExpenseRecurringBankAccountId` | `string` | Yes | Yes | ID of the related default expense recurring bank account. | `null` | | `data.email` | `string` | Yes | Yes | Email address associated with the identity. | `"owner@example.com"` | | `data.phone` | `string` | Yes | Yes | phone for this setting. | `"+966500000000"` | | `data.address` | `string` | Yes | Yes | address for this setting. | `"King Fahd Road"` | | `data.city` | `string` | Yes | Yes | city for this setting. | `"Riyadh"` | | `data.state` | `string` | Yes | Yes | Current state of the record or operation. | `"Riyadh"` | | `data.postalCode` | `string` | Yes | Yes | postal code for this setting. | `"Consulting services"` | | `data.country` | `string` | Yes | Yes | country for this setting. | `"SA"` | | `data.createdBy` | `string` | Yes | No | Identifier of the identity that created the record. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1B"` | | `data.updatedBy` | `string` | Yes | Yes | Identifier of the identity that last updated the record. | `null` | | `data.deletedBy` | `string` | Yes | Yes | deleted by for this setting. | `null` | | `data.fiscalYearStartAt` | `string` | Yes | Yes | ISO 8601 timestamp for fiscal year start. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1A", "name": "Acme workspace", "slug": "acme-workspace", "officialName": "Consulting services", "tradeName": "Consulting services", "registrationNumber": "CR-0001234567", "taxId": "100.00", "defaultCurrencyId": null, "defaultInvoiceBankAccountId": null, "defaultIncomeBankAccountId": null, "defaultAssetBankAccountId": null, "defaultExpenseBankAccountId": null, "defaultPayoutBankAccountId": null, "defaultExpenseRecurringBankAccountId": null, "email": "owner@example.com", "phone": "+966500000000", "address": "King Fahd Road", "city": "Riyadh", "state": "Riyadh", "postalCode": "Consulting services", "country": "SA", "createdBy": "01JQ2T5Y5Q3R8W9N6M4K2H7P1B", "updatedBy": null, "deletedBy": null, "fiscalYearStartAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/settings" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "field": "name", "value": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/settings", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "field": "name", "value": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/settings failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Create a workspace avatar upload **POST** `/v1/settings/avatar-uploads` Create a workspace avatar upload. - Canonical URL: [https://docs.nqd.app/v1/reference/settings/avatar-uploads/create](https://docs.nqd.app/v1/reference/settings/avatar-uploads/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `mime` | `string` | Yes | No | mime for this setting. (Allowed values: "image/png", "image/jpeg", "image/jpg", "image/svg+xml") | `"image/png"` | | `size` | `number` | Yes | No | size for this setting. (maximum 2097152, greater than 0) | `100` | ```json { "mime": "image/png", "size": 100 } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.signedUrl` | `string` | Yes | No | signed url for this setting. | `"https://example.com/hooks/nqd"` | | `data.publicUrl` | `string` | Yes | No | public url for this setting. | `"https://example.com/hooks/nqd"` | ```json { "data": { "signedUrl": "https://example.com/hooks/nqd", "publicUrl": "https://example.com/hooks/nqd" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/settings/avatar-uploads" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "mime": "image/png", "size": 100 }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/settings/avatar-uploads", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "mime": "image/png", "size": 100 }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/settings/avatar-uploads failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List tags **GET** `/v1/tags` Retrieve matching tags. - Canonical URL: [https://docs.nqd.app/v1/reference/tags/list](https://docs.nqd.app/v1/reference/tags/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter tags by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter tags by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[color]` | `string` | No | No | Filter tags by color. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.slate"` | | `filter[createdAt]` | `string` | No | No | Filter tags by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter tags by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedAt]` | `string` | No | No | Filter tags by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M", "name": "NQD record", "color": "slate", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/tags" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/tags", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/tags failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve tag **GET** `/v1/tags/{tagId}` Return the addressed tag. - Canonical URL: [https://docs.nqd.app/v1/reference/tags/retrieve](https://docs.nqd.app/v1/reference/tags/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `tagId` | `string` | Yes | No | An opaque tag resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M", "name": "NQD record", "color": "slate", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create tags **POST** `/v1/tags` Create tags from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/tags/create](https://docs.nqd.app/v1/reference/tags/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 200 characters.) | `"NQD record"` | | `color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | ```json [ { "name": "NQD record", "color": "slate" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M", "name": "NQD record", "color": "slate", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/tags" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "color": "slate" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/tags", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "color": "slate" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/tags failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert tag **PUT** `/v1/tags/{tagId}` Create or update the addressed tag. - Canonical URL: [https://docs.nqd.app/v1/reference/tags/upsert](https://docs.nqd.app/v1/reference/tags/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `tagId` | `string` | Yes | No | An opaque tag resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 200 characters.) | `"NQD record"` | | `color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | ```json { "name": "NQD record", "color": "slate" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M", "name": "NQD record", "color": "slate", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record", "color": "slate" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record", "color": "slate" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete tag **DELETE** `/v1/tags/{tagId}` Delete tag. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/tags/delete](https://docs.nqd.app/v1/reference/tags/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `tagId` | `string` | Yes | No | An opaque tag resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/tags/01JQ2T5Y5Q3R8W9N6M4K2H7P1M failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert tags in a batch **PUT** `/v1/tags` Upsert tags atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/tags/bulk-upsert](https://docs.nqd.app/v1/reference/tags/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 200 characters.) | `"NQD record"` | | `color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | ```json [ { "name": "NQD record", "color": "slate", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1M"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].color` | `string` | Yes | No | color for this tag. (Allowed values: "slate", "red", "orange", "amber", "green", "teal", "blue", "indigo", "violet", "pink") | `"slate"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M", "name": "NQD record", "color": "slate", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/tags" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "color": "slate", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/tags", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "color": "slate", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1M" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/tags failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List transactions **GET** `/v1/transactions` Retrieve matching transactions. - Canonical URL: [https://docs.nqd.app/v1/reference/transactions/list](https://docs.nqd.app/v1/reference/transactions/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter transactions by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[amount]` | `string` | No | No | Filter transactions by amount. Use operator.value syntax. (eq, neq, gt, gte, lt, lte operators) | `"eq.100.00"` | | `filter[direction]` | `string` | No | No | Filter transactions by direction. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.inbound"` | | `filter[createdAt]` | `string` | No | No | Filter transactions by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[bankAccountId]` | `string` | No | No | Filter transactions by bankAccountId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[originalId]` | `string` | No | No | Filter transactions by originalId. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceId]` | `string` | No | No | Filter transactions by sourceId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[sourceType]` | `string` | No | No | Filter transactions by sourceType. Use operator.value syntax. (eq, neq, in operators) | `"eq.invoice"` | | `filter[currencyCode]` | `string` | No | No | Filter transactions by currencyCode. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.SAR"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,source"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,amount.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data[].source` | `object` | Yes | Yes | source for this transaction. | — | | `data[].source.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data[].source.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "invoice", "expense", "income", "payout", "asset") | `"invoice"` | | `data[].amount` | `string` | Yes | No | Exact decimal string used for financial calculations. Do not round or convert it to a display number. | `"100.00"` | | `data[].direction` | `string` | Yes | No | direction for this transaction. (Allowed values: "inbound", "outbound") | `"inbound"` | | `data[].currency` | `object` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | — | | `data[].currency.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1F"` | | `data[].currency.code` | `string` | Yes | No | ISO 4217 currency code, such as SAR or USD. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion` | `object` | Yes | Yes | Currency conversion quote used for reporting, including source, target, and rate. | — | | `data[].currency.conversion.from` | `string` | Yes | No | ISO 4217 code of the source currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.to` | `string` | Yes | No | ISO 4217 code of the target reporting currency in this persisted quote. (Minimum length: 1 character., Maximum length: 128 characters.) | `"SAR"` | | `data[].currency.conversion.rate` | `string` | Yes | No | Exact decimal conversion rate from the quote source currency to its target currency. (Maximum length: 128 characters.) | `"1.00"` | | `data[].bankAccountId` | `string` | Yes | Yes | ID of the related bank account. | `null` | | `data[].accountLabel` | `string` | No | Yes | account label for this transaction. | `"Consulting services"` | | `data[].originalId` | `string` | Yes | Yes | ID of the related original. | `"Consulting services"` | | `data[].context` | `object` | Yes | No | context for this transaction. | — | | `data[].context.heading` | `string` | Yes | No | heading within context. | `"Operating account"` | | `data[].context.subheading` | `string` | Yes | No | subheading within context. | `"Operating account"` | | `data[].context.websites` | `string[]` | Yes | No | websites within context. | `["https://example.com/hooks/nqd"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "source": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "type": "invoice" }, "amount": "100.00", "direction": "inbound", "currency": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1F", "code": "SAR", "conversion": { "from": "SAR", "to": "SAR", "rate": "1.00" } }, "bankAccountId": null, "originalId": "Consulting services", "context": { "heading": "Operating account", "subheading": "Operating account", "websites": [ "https://example.com/hooks/nqd" ] }, "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/transactions" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/transactions", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/transactions failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # Delete a transaction **DELETE** `/v1/transactions/{transactionId}` Permanently delete a transaction and remove it from effective payment totals and reports. - Canonical URL: [https://docs.nqd.app/v1/reference/transactions/delete](https://docs.nqd.app/v1/reference/transactions/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `transactionId` | `string` | Yes | No | An opaque transaction resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `expectedCreatedAt` | `string` | No | No | Optional expected created at filter or query option. | `"2026-01-15T12:00:00.000Z"` | ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/transactions/01JQ2T5Y5Q3R8W9N6M4K2H7P1X" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/transactions/01JQ2T5Y5Q3R8W9N6M4K2H7P1X", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/transactions/01JQ2T5Y5Q3R8W9N6M4K2H7P1X failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # Update a transaction **PATCH** `/v1/transactions/{transactionId}` Update a transaction amount, creation date, or both in place while preserving its identity, currency, account, and source. - Canonical URL: [https://docs.nqd.app/v1/reference/transactions/update](https://docs.nqd.app/v1/reference/transactions/update) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `transactionId` | `string` | Yes | No | An opaque transaction resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `amount` | `string` | No | Yes | Exact decimal string used for financial calculations. Do not round or convert it to a display number. (Maximum length: 128 characters.) | `"100.00"` | | `createdAt` | `string` | No | Yes | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `expectedCreatedAt` | `string` | No | Yes | ISO 8601 timestamp for expected created. | `"2026-01-15T12:00:00.000Z"` | ```json { "amount": "100.00" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1X"` | | `data.repeated` | `boolean` | Yes | No | repeated for this transaction. | `true` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1X", "repeated": true } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PATCH "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/transactions/01JQ2T5Y5Q3R8W9N6M4K2H7P1X" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "amount": "100.00" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/transactions/01JQ2T5Y5Q3R8W9N6M4K2H7P1X", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PATCH", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "amount": "100.00" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PATCH /v1/transactions/01JQ2T5Y5Q3R8W9N6M4K2H7P1X failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Financial sources describe what the money or wealth represents: Invoice, Income, Expense, Payout, and Asset. - Transactions describe cash events against a source. A source can be unpaid or partially paid; a Transaction records an actual cash movement. - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Payment status and settlement dates come from Transactions; source headers do not accept a separate paidAt value. --- # List units **GET** `/v1/units` Retrieve matching units. - Canonical URL: [https://docs.nqd.app/v1/reference/units/list](https://docs.nqd.app/v1/reference/units/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[code]` | `string` | No | No | Filter units by code. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[category]` | `string` | No | No | Filter units by category. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[labelEn]` | `string` | No | No | Filter units by labelEn. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[labelAr]` | `string` | No | No | Filter units by labelAr. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[createdAt]` | `string` | No | No | Filter units by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter units by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[deletedAt]` | `string` | No | No | Filter units by deletedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"code,category"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"code.asc,category.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"hour"` | | `data[].labelEn` | `string` | Yes | No | label en for this unit. | `"Consulting services"` | | `data[].labelAr` | `string` | Yes | No | label ar for this unit. | `"خدمات استشارية"` | | `data[].category` | `string` | Yes | No | Category assigned to the delivery attempt. | `"general"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "code": "hour", "labelEn": "Consulting services", "labelAr": "خدمات استشارية", "category": "general", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/units" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/units", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/units failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve unit **GET** `/v1/units/{code}` Return the addressed unit. - Canonical URL: [https://docs.nqd.app/v1/reference/units/retrieve](https://docs.nqd.app/v1/reference/units/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | Yes | No | Catalog unit code used to address the workspace unit. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"hour"` | | `data.category` | `string` | Yes | No | Category assigned to the delivery attempt. | `"general"` | | `data.labelEn` | `string` | Yes | No | label en for this unit. | `"Consulting services"` | | `data.labelAr` | `string` | Yes | No | label ar for this unit. | `"خدمات استشارية"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "code": "hour", "category": "general", "labelEn": "Consulting services", "labelAr": "خدمات استشارية", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/units/hour" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/units/hour", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/units/hour failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create units **POST** `/v1/units` Create units from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/units/create](https://docs.nqd.app/v1/reference/units/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | Yes | No | Stable code used to identify this catalog value or machine-readable result. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `labelEn` | `string` | Yes | No | label en for this unit. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Consulting services"` | | `labelAr` | `string` | Yes | No | label ar for this unit. (Minimum length: 1 character., Maximum length: 255 characters.) | `"خدمات استشارية"` | ```json [ { "code": "hour", "labelEn": "Consulting services", "labelAr": "خدمات استشارية" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/units/hour"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"hour"` | | `data[].category` | `string` | Yes | No | Category assigned to the delivery attempt. | `"general"` | | `data[].labelEn` | `string` | Yes | No | label en for this unit. | `"Consulting services"` | | `data[].labelAr` | `string` | Yes | No | label ar for this unit. | `"خدمات استشارية"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "code": "hour", "category": "general", "labelEn": "Consulting services", "labelAr": "خدمات استشارية", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/units" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "code": "hour", "labelEn": "Consulting services", "labelAr": "خدمات استشارية" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/units", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "code": "hour", "labelEn": "Consulting services", "labelAr": "خدمات استشارية" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/units failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert unit **PUT** `/v1/units/{code}` Create or update the addressed unit. - Canonical URL: [https://docs.nqd.app/v1/reference/units/upsert](https://docs.nqd.app/v1/reference/units/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | Yes | No | Catalog unit code used to address the workspace unit. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `labelEn` | `string` | Yes | No | label en for this unit. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Consulting services"` | | `labelAr` | `string` | Yes | No | label ar for this unit. (Minimum length: 1 character., Maximum length: 255 characters.) | `"خدمات استشارية"` | ```json { "labelEn": "Consulting services", "labelAr": "خدمات استشارية" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"hour"` | | `data.category` | `string` | Yes | No | Category assigned to the delivery attempt. | `"general"` | | `data.labelEn` | `string` | Yes | No | label en for this unit. | `"Consulting services"` | | `data.labelAr` | `string` | Yes | No | label ar for this unit. | `"خدمات استشارية"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": { "code": "hour", "category": "general", "labelEn": "Consulting services", "labelAr": "خدمات استشارية", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/units/hour" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "labelEn": "Consulting services", "labelAr": "خدمات استشارية" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/units/hour", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "labelEn": "Consulting services", "labelAr": "خدمات استشارية" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/units/hour failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Archive unit **DELETE** `/v1/units/{code}` Archive unit. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/units/delete](https://docs.nqd.app/v1/reference/units/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | Yes | No | Catalog unit code used to address the workspace unit. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/units/hour" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/units/hour", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/units/hour failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert units in a batch **PUT** `/v1/units` Upsert units atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/units/bulk-upsert](https://docs.nqd.app/v1/reference/units/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `code` | `string` | Yes | No | Stable code used to identify this catalog value or machine-readable result. (Minimum length: 1 character., Maximum length: 128 characters.) | `"hour"` | | `labelEn` | `string` | Yes | No | label en for this unit. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Consulting services"` | | `labelAr` | `string` | Yes | No | label ar for this unit. (Minimum length: 1 character., Maximum length: 255 characters.) | `"خدمات استشارية"` | ```json [ { "code": "hour", "labelEn": "Consulting services", "labelAr": "خدمات استشارية" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"hour"` | | `data[].category` | `string` | Yes | No | Category assigned to the delivery attempt. | `"general"` | | `data[].labelEn` | `string` | Yes | No | label en for this unit. | `"Consulting services"` | | `data[].labelAr` | `string` | Yes | No | label ar for this unit. | `"خدمات استشارية"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].deletedAt` | `string` | Yes | Yes | ISO 8601 timestamp when the record was deleted, or null when it exists. | `null` | ```json { "data": [ { "code": "hour", "category": "general", "labelEn": "Consulting services", "labelAr": "خدمات استشارية", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z", "deletedAt": null } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/units" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "code": "hour", "labelEn": "Consulting services", "labelAr": "خدمات استشارية" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/units", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "code": "hour", "labelEn": "Consulting services", "labelAr": "خدمات استشارية" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/units failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Read current billing usage **GET** `/v1/usage` Return current billing usage. - Canonical URL: [https://docs.nqd.app/v1/reference/usage/retrieve](https://docs.nqd.app/v1/reference/usage/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.currentPlan` | `object` | Yes | No | current plan for this usage. | — | | `data.currentPlan.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"free"` | | `data.currentPlan.kind` | `string` | Yes | No | kind within current plan. (Allowed values: "free", "pro", "business", "enterprise", "elite", "vip") | `"free"` | | `data.currentPlan.tier` | `string` | Yes | No | tier within current plan. (Allowed values: "free", "solo", "team", "business", "enterprise") | `"free"` | | `data.currentPlan.name` | `object` | Yes | No | Display name of the record. | — | | `data.currentPlan.name.en` | `string` | Yes | No | en within name. | `"Consulting services"` | | `data.currentPlan.name.ar` | `string` | Yes | No | ar within name. | `"Consulting services"` | | `data.currentPlan.monthlyPrice` | `number` | Yes | No | monthly price within current plan. | `100` | | `data.currentPlan.yearlyPrice` | `number` | Yes | No | yearly price within current plan. | `100` | | `data.currentPlan.currency` | `string` | Yes | No | Referenced currency with its opaque ID and ISO 4217 currency code. | `"Consulting services"` | | `data.currentPlan.limits` | `object` | Yes | No | limits within current plan. | — | | `data.currentPlan.limits.paymentsPerMonth` | `number` | Yes | No | payments per month within limits. | `100` | | `data.currentPlan.features` | `object` | Yes | No | features within current plan. | — | | `data.currentPlan.features.recurringAutomation` | `boolean` | Yes | No | recurring automation within features. | `true` | | `data.currentPlan.features.teamCollaboration` | `boolean` | Yes | No | team collaboration within features. | `true` | | `data.currentPlan.features.webhooks` | `boolean` | Yes | No | webhooks within features. | `true` | | `data.participantCount` | `number` | Yes | No | participant count for this usage. | `1` | | `data.billingSubscription` | `object` | Yes | Yes | billing subscription for this usage. | — | | `data.billingSubscription.status` | `string` | Yes | Yes | Current status of the record or operation. | `"active"` | | `data.billingSubscription.productName` | `string` | Yes | Yes | product name within billing subscription. | `"Consulting services"` | | `data.billingSubscription.variantName` | `string` | Yes | Yes | variant name within billing subscription. | `"Consulting services"` | | `data.billingSubscription.renewsAt` | `string` | Yes | Yes | ISO 8601 timestamp for renews. | `"2026-01-15T12:00:00.000Z"` | | `data.billingSubscription.endsAt` | `string` | Yes | Yes | ISO 8601 timestamp for ends. | `"2026-01-15T12:00:00.000Z"` | | `data.billingSubscription.cancelledAt` | `string` | Yes | Yes | ISO 8601 timestamp for cancelled. | `null` | | `data.billingSubscription.trialEndsAt` | `string` | Yes | Yes | ISO 8601 timestamp for trial ends. | `"2026-01-15T12:00:00.000Z"` | | `data.billingInvoicesCount` | `number` | Yes | No | billing invoices count for this usage. | `1` | | `data.paymentUsage` | `object` | Yes | Yes | payment usage for this usage. | — | | `data.paymentUsage.planId` | `string` | Yes | No | ID of the related plan. | `"free"` | | `data.paymentUsage.capacity` | `number` | Yes | No | capacity within payment usage. | `100` | | `data.paymentUsage.used` | `number` | Yes | No | used within payment usage. | `100` | | `data.paymentUsage.remaining` | `number` | Yes | No | remaining within payment usage. | `0` | | `data.paymentUsage.activeProjects` | `number` | Yes | No | active projects within payment usage. | `100` | | `data.paymentUsage.monthStartedAt` | `string` | Yes | No | ISO 8601 timestamp for month started. | `"2026-01-15T12:00:00.000Z"` | | `data.paymentUsage.monthEndsAt` | `string` | Yes | No | ISO 8601 timestamp for month ends. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "currentPlan": { "id": "free", "kind": "free", "tier": "free", "name": { "en": "Consulting services", "ar": "Consulting services" }, "monthlyPrice": 100, "yearlyPrice": 100, "currency": "Consulting services", "limits": { "paymentsPerMonth": 100 }, "features": { "recurringAutomation": true, "teamCollaboration": true, "webhooks": true } }, "participantCount": 1, "billingSubscription": { "status": "active", "productName": "Consulting services", "variantName": "Consulting services", "renewsAt": "2026-01-15T12:00:00.000Z", "endsAt": "2026-01-15T12:00:00.000Z", "cancelledAt": null, "trialEndsAt": "2026-01-15T12:00:00.000Z" }, "billingInvoicesCount": 1, "paymentUsage": { "planId": "free", "capacity": 100, "used": 100, "remaining": 0, "activeProjects": 100, "monthStartedAt": "2026-01-15T12:00:00.000Z", "monthEndsAt": "2026-01-15T12:00:00.000Z" } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/usage" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/usage", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/usage failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List vendors **GET** `/v1/vendors` Retrieve matching vendors. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/list](https://docs.nqd.app/v1/reference/vendors/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter vendors by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter vendors by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter vendors by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[type]` | `string` | No | No | Filter vendors by type. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.company"` | | `filter[notes]` | `string` | No | No | Filter vendors by notes. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[createdAt]` | `string` | No | No | Filter vendors by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter vendors by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[tags]` | `string` | No | No | Filter vendors by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string[]` | Yes | Yes | website for this vendor. | `["https://example.com/hooks/nqd"]` | | `data[].industry` | `string[]` | Yes | Yes | industry for this vendor. | `["Consulting services"]` | | `data[].type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "tags": [ "equipment" ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/vendors failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Retrieve vendor **GET** `/v1/vendors/{vendorId}` Return the addressed vendor. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/retrieve](https://docs.nqd.app/v1/reference/vendors/retrieve) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `vendorId` | `string` | Yes | No | An opaque vendor resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.website` | `string[]` | Yes | Yes | website for this vendor. | `["https://example.com/hooks/nqd"]` | | `data.industry` | `string[]` | Yes | Yes | industry for this vendor. | `["Consulting services"]` | | `data.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create vendors **POST** `/v1/vendors` Create vendors from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/create](https://docs.nqd.app/v1/reference/vendors/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string[]` | No | Yes | website for this vendor. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `location` | `string` | Yes | No | Relative URL for retrieving the created resource. | `"/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string[]` | Yes | Yes | website for this vendor. | `["https://example.com/hooks/nqd"]` | | `data[].industry` | `string[]` | Yes | Yes | industry for this vendor. | `["Consulting services"]` | | `data[].type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/vendors failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert vendor **PUT** `/v1/vendors/{vendorId}` Create or update the addressed vendor. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/upsert](https://docs.nqd.app/v1/reference/vendors/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `vendorId` | `string` | Yes | No | An opaque vendor resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string[]` | No | Yes | website for this vendor. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | ```json { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.website` | `string[]` | Yes | Yes | website for this vendor. | `["https://example.com/hooks/nqd"]` | | `data.industry` | `string[]` | Yes | Yes | industry for this vendor. | `["Consulting services"]` | | `data.type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record", "description": "Consulting services for January 2026", "type": "company" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # Delete vendor **DELETE** `/v1/vendors/{vendorId}` Delete vendor. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/delete](https://docs.nqd.app/v1/reference/vendors/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `vendorId` | `string` | Yes | No | An opaque vendor resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Upsert vendors in a batch **PUT** `/v1/vendors` Upsert vendors atomically. Send an array of complete writable records, each with its resource ID. One invalid record rejects the entire batch. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/bulk-upsert](https://docs.nqd.app/v1/reference/vendors/bulk-upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD record"` | | `description` | `string` | No | Yes | Human-readable description of the resource. (Maximum length: 10000 characters.) | `"Consulting services for January 2026"` | | `website` | `string[]` | No | Yes | website for this vendor. (at most 100 items) | `["https://example.com/hooks/nqd"]` | | `type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `tags` | `string[]` | No | Yes | Tags assigned to the record. (at most 100 items) | `["equipment"]` | | `id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ```json [ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" } ] ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].website` | `string[]` | Yes | Yes | website for this vendor. | `["https://example.com/hooks/nqd"]` | | `data[].industry` | `string[]` | Yes | Yes | industry for this vendor. | `["Consulting services"]` | | `data[].type` | `string` | Yes | No | Type of the record or operation. (Allowed values: "company", "individual", "government") | `"company"` | | `data[].notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data[].tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "name": "NQD record", "description": "Consulting services for January 2026", "website": [ "https://example.com/hooks/nqd" ], "industry": [ "Consulting services" ], "type": "company", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "description": "Consulting services for January 2026", "type": "company", "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C" } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/vendors failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. --- # List vendor contacts **GET** `/v1/vendors/{vendorId}/contacts` List vendor contacts. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/contacts/list](https://docs.nqd.app/v1/reference/vendors/contacts/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `vendorId` | `string` | Yes | No | An opaque vendor resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter vendors by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[clientId]` | `string` | No | No | Filter vendors by clientId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[vendorId]` | `string` | No | No | Filter vendors by vendorId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `filter[name]` | `string` | No | No | Filter vendors by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[description]` | `string` | No | No | Filter vendors by description. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[bank]` | `string` | No | No | Filter vendors by bank. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[iban]` | `string` | No | No | Filter vendors by iban. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, in, is operators) | `"eq.example"` | | `filter[tags]` | `string` | No | No | Filter vendors by tags. Use operator.value syntax. (in, is operators) | `"in.(example)"` | | `filter[createdAt]` | `string` | No | No | Filter vendors by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter vendors by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,clientId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,clientId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data[].clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data[].vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data[].name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data[].description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data[].email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data[].phone` | `string[]` | Yes | Yes | phone for this vendor. | `["+966500000000"]` | | `data[].website` | `string[]` | Yes | Yes | website for this vendor. | `["https://example.com/hooks/nqd"]` | | `data[].position` | `string[]` | Yes | Yes | position for this vendor. | `["Consulting services"]` | | `data[].bank` | `string` | Yes | Yes | bank for this vendor. | `"NQD Bank"` | | `data[].iban` | `string` | Yes | Yes | iban for this vendor. | `"SA0380000000608010167519"` | | `data[].tags` | `string[]` | Yes | No | Tags assigned to the record. | `["equipment"]` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bank": "NQD Bank", "iban": "SA0380000000608010167519", "tags": [ "equipment" ], "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Add a contact to a vendor **POST** `/v1/vendors/{vendorId}/contacts/{contactId}` Add a contact to a vendor. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/contacts/create](https://docs.nqd.app/v1/reference/vendors/contacts/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `vendorId` | `string` | Yes | No | An opaque vendor resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `contactId` | `string` | Yes | No | An opaque contact resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `data.clientId` | `string` | Yes | Yes | Optional client relationship for this contact. A contact may also reference a vendor; when both are provided they must resolve to the same party. A null clientId alone does not mean workspace ownership when vendorId is set. | `null` | | `data.vendorId` | `string` | Yes | Yes | Optional vendor relationship for this contact. A contact may also reference a client; when both are provided they must resolve to the same party. Both relationship IDs null means the current workspace owns the contact. | `null` | | `data.name` | `string` | Yes | Yes | Display name of the record. | `"NQD record"` | | `data.description` | `string` | Yes | Yes | Optional human-readable description of the record. | `"Consulting services for January 2026"` | | `data.email` | `string[]` | Yes | Yes | Email address associated with the identity. | `["owner@example.com"]` | | `data.phone` | `string[]` | Yes | Yes | phone for this vendor. | `["+966500000000"]` | | `data.website` | `string[]` | Yes | Yes | website for this vendor. | `["https://example.com/hooks/nqd"]` | | `data.position` | `string[]` | Yes | Yes | position for this vendor. | `["Consulting services"]` | | `data.bankName` | `string` | Yes | Yes | bank name for this vendor. | `"NQD Bank"` | | `data.iban` | `string` | Yes | Yes | iban for this vendor. | `"SA0380000000608010167519"` | | `data.notes` | `string` | Yes | Yes | Notes attached to the record. | `"Consulting services"` | | `data.tags` | `string[]` | No | Yes | Tags assigned to the record. | `["equipment"]` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1C", "clientId": null, "vendorId": null, "name": "NQD record", "description": "Consulting services for January 2026", "email": [ "owner@example.com" ], "phone": [ "+966500000000" ], "website": [ "https://example.com/hooks/nqd" ], "position": [ "Consulting services" ], "bankName": "NQD Bank", "iban": "SA0380000000608010167519", "notes": "Consulting services", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Remove a contact from a vendor **DELETE** `/v1/vendors/{vendorId}/contacts/{contactId}` Remove a contact from a vendor. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/vendors/contacts/delete](https://docs.nqd.app/v1/reference/vendors/contacts/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `vendorId` | `string` | Yes | No | An opaque vendor resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1C"` | | `contactId` | `string` | Yes | No | An opaque contact resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1E"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/vendors/01JQ2T5Y5Q3R8W9N6M4K2H7P1C/contacts/01JQ2T5Y5Q3R8W9N6M4K2H7P1E failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # List webhooks **GET** `/v1/webhooks` List workspace webhooks and their delivery state with cursor pagination. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/list](https://docs.nqd.app/v1/reference/webhooks/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter webhooks by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter webhooks by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[destination]` | `string` | No | No | Filter webhooks by destination. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[status]` | `string` | No | No | Filter webhooks by status. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.pending_verification"` | | `filter[verifiedAt]` | `string` | No | No | Filter webhooks by verifiedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[createdAt]` | `string` | No | No | Filter webhooks by createdAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[updatedAt]` | `string` | No | No | Filter webhooks by updatedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | | `search` | `string` | No | No | Search matching resource fields. | `"consulting"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data[].name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data[].destination` | `string` | Yes | No | destination for this webhook. | `"https://example.com/hooks/nqd"` | | `data[].events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["Consulting services"]` | | `data[].status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending_verification", "active", "paused", "deleted") | `"pending_verification"` | | `data[].verifiedAt` | `string` | Yes | Yes | ISO 8601 timestamp for verified. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "Consulting services" ], "status": "pending_verification", "verifiedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/webhooks failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. - Use the returned nextCursor for the next page. Do not combine cursor with before, beforeId, or beforeAttempt. --- # Create webhooks **POST** `/v1/webhooks` Create webhooks from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/create](https://docs.nqd.app/v1/reference/webhooks/create) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `destination` | `string` | Yes | No | destination for this webhook. (Minimum length: 1 character., Maximum length: 2048 characters.) | `"https://example.com/hooks/nqd"` | | `events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["retention.update"]` | ```json [ { "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "retention.update" ] } ] ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].webhook` | `object` | Yes | No | webhook for this webhook. | — | | `data[].webhook.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data[].webhook.name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data[].webhook.destination` | `string` | Yes | No | destination within webhook. | `"https://example.com/hooks/nqd"` | | `data[].webhook.events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["Consulting services"]` | | `data[].webhook.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending_verification", "active", "paused", "deleted") | `"pending_verification"` | | `data[].webhook.verifiedAt` | `string` | Yes | Yes | ISO 8601 timestamp for verified. | `"2026-01-15T12:00:00.000Z"` | | `data[].webhook.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data[].webhook.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data[].signingSecret` | `string` | Yes | No | signing secret for this webhook. | `"whsec_01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ```json { "data": [ { "webhook": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "Consulting services" ], "status": "pending_verification", "verifiedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" }, "signingSecret": "whsec_01JQ2T5Y5Q3R8W9N6M4K2H7P1A" } ] } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '[ { "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "retention.update" ] } ]' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify([ { "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "retention.update" ] } ]), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/webhooks failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # Update webhooks **PUT** `/v1/webhooks/{webhookId}` Update webhooks. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/upsert](https://docs.nqd.app/v1/reference/webhooks/upsert) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | No | Yes | Display name of the resource. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `destination` | `string` | No | Yes | destination for this webhook. (Minimum length: 1 character., Maximum length: 2048 characters.) | `"https://example.com/hooks/nqd"` | | `events` | `string[]` | No | Yes | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["retention.update"]` | ```json { "name": "NQD record" } ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data.name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data.destination` | `string` | Yes | No | destination for this webhook. | `"https://example.com/hooks/nqd"` | | `data.events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["Consulting services"]` | | `data.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending_verification", "active", "paused", "deleted") | `"pending_verification"` | | `data.verifiedAt` | `string` | Yes | Yes | ISO 8601 timestamp for verified. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "Consulting services" ], "status": "pending_verification", "verifiedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request PUT "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{ "name": "NQD record" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "PUT", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({ "name": "NQD record" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `PUT /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Send the complete writable representation or change set. Use the latest updatedAt for If-Match. - Inspect webhook state and delivery attempts through the related resources. --- # Delete webhook **DELETE** `/v1/webhooks/{webhookId}` Delete webhook. A successful request returns 204 with no response body. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/delete](https://docs.nqd.app/v1/reference/webhooks/delete) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters This operation has no query parameters. ## Request body This operation does not accept a JSON request body. ## Responses ### 204 — Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body This response has no body. ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request DELETE "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "DELETE", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `DELETE /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # List webhook deliveries **GET** `/v1/webhooks/{webhookId}/deliveries` List delivery attempts for a workspace webhook with cursor pagination and attempt boundaries. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/deliveries/list](https://docs.nqd.app/v1/reference/webhooks/deliveries/list) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[webhookId]` | `string` | No | No | Filter webhooks by webhookId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `filter[logId]` | `string` | No | No | Filter webhooks by logId. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P2A"` | | `filter[attempt]` | `string` | No | No | Filter webhooks by attempt. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.1"` | | `filter[status]` | `string` | No | No | Filter webhooks by status. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.pending"` | | `filter[category]` | `string` | No | No | Filter webhooks by category. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[nextAttemptAt]` | `string` | No | No | Filter webhooks by nextAttemptAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[leaseExpiresAt]` | `string` | No | No | Filter webhooks by leaseExpiresAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[attemptedAt]` | `string` | No | No | Filter webhooks by attemptedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[completedAt]` | `string` | No | No | Filter webhooks by completedAt. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `filter[latencyMs]` | `string` | No | No | Filter webhooks by latencyMs. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.1"` | | `filter[httpStatus]` | `string` | No | No | Filter webhooks by httpStatus. Use operator.value syntax. (eq, neq, gt, gte, lt, lte, is operators) | `"eq.1"` | | `filter[responseExcerpt]` | `string` | No | No | Filter webhooks by responseExcerpt. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[createdAt]` | `string` | No | No | Filter webhooks by createdAt. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.2026-01-15T12:00:00Z"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"webhookId,logId"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"webhookId.asc,logId.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].webhookId` | `string` | Yes | No | ID of the related webhook. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data[].logId` | `string` | Yes | No | ID of the related log. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2A"` | | `data[].attempt` | `number` | Yes | No | attempt for this webhook. | `100` | | `data[].status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending", "delivering", "succeeded", "failed", "unknown") | `"pending"` | | `data[].category` | `string` | Yes | Yes | Category assigned to the delivery attempt. | `"general"` | | `data[].latencyMs` | `number` | Yes | Yes | latency ms for this webhook. | `100` | | `data[].httpStatus` | `number` | Yes | Yes | http status for this webhook. | `100` | | `data[].responseExcerpt` | `string` | Yes | Yes | response excerpt for this webhook. | `"OK"` | | `data[].nextAttemptAt` | `string` | Yes | Yes | ISO 8601 timestamp for next attempt. | `"2026-01-15T12:00:00.000Z"` | | `data[].leaseExpiresAt` | `string` | Yes | Yes | ISO 8601 timestamp for lease expires. | `"2026-01-15T12:00:00.000Z"` | | `data[].attemptedAt` | `string` | Yes | Yes | ISO 8601 timestamp for attempted. | `"2026-01-15T12:00:00.000Z"` | | `data[].completedAt` | `string` | Yes | Yes | ISO 8601 timestamp for completed. | `"2026-01-15T12:00:00.000Z"` | | `data[].createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "webhookId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "logId": "01JQ2T5Y5Q3R8W9N6M4K2H7P2A", "attempt": 100, "status": "pending", "category": "general", "latencyMs": 100, "httpStatus": 100, "responseExcerpt": "OK", "nextAttemptAt": "2026-01-15T12:00:00.000Z", "leaseExpiresAt": "2026-01-15T12:00:00.000Z", "attemptedAt": "2026-01-15T12:00:00.000Z", "completedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/deliveries" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/deliveries", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/deliveries failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. - Use the returned nextCursor for the next page. Do not combine cursor with before, beforeId, or beforeAttempt. --- # Retry a failed webhook delivery **POST** `/v1/webhooks/{webhookId}/deliveries/{logId}/retry` Retry the failed webhook delivery. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/deliveries/retry](https://docs.nqd.app/v1/reference/webhooks/deliveries/retry) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `logId` | `string` | Yes | No | An opaque log resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2A"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.webhookId` | `string` | Yes | No | ID of the related webhook. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data.logId` | `string` | Yes | No | ID of the related log. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P2A"` | | `data.attempt` | `number` | Yes | No | attempt for this webhook. | `100` | | `data.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending", "delivering", "succeeded", "failed", "unknown") | `"pending"` | | `data.category` | `string` | Yes | Yes | Category assigned to the delivery attempt. | `"general"` | | `data.latencyMs` | `number` | Yes | Yes | latency ms for this webhook. | `100` | | `data.httpStatus` | `number` | Yes | Yes | http status for this webhook. | `100` | | `data.responseExcerpt` | `string` | Yes | Yes | response excerpt for this webhook. | `"OK"` | | `data.nextAttemptAt` | `string` | Yes | Yes | ISO 8601 timestamp for next attempt. | `"2026-01-15T12:00:00.000Z"` | | `data.leaseExpiresAt` | `string` | Yes | Yes | ISO 8601 timestamp for lease expires. | `"2026-01-15T12:00:00.000Z"` | | `data.attemptedAt` | `string` | Yes | Yes | ISO 8601 timestamp for attempted. | `"2026-01-15T12:00:00.000Z"` | | `data.completedAt` | `string` | Yes | Yes | ISO 8601 timestamp for completed. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "webhookId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "logId": "01JQ2T5Y5Q3R8W9N6M4K2H7P2A", "attempt": 100, "status": "pending", "category": "general", "latencyMs": 100, "httpStatus": 100, "responseExcerpt": "OK", "nextAttemptAt": "2026-01-15T12:00:00.000Z", "leaseExpiresAt": "2026-01-15T12:00:00.000Z", "attemptedAt": "2026-01-15T12:00:00.000Z", "completedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/deliveries/01JQ2T5Y5Q3R8W9N6M4K2H7P2A/retry" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/deliveries/01JQ2T5Y5Q3R8W9N6M4K2H7P2A/retry", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/deliveries/01JQ2T5Y5Q3R8W9N6M4K2H7P2A/retry failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # Pause webhook deliveries **POST** `/v1/webhooks/{webhookId}/pause` Pause deliveries for the addressed webhook. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/pause](https://docs.nqd.app/v1/reference/webhooks/pause) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data.name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data.destination` | `string` | Yes | No | destination for this webhook. | `"https://example.com/hooks/nqd"` | | `data.events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["Consulting services"]` | | `data.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending_verification", "active", "paused", "deleted") | `"pending_verification"` | | `data.verifiedAt` | `string` | Yes | Yes | ISO 8601 timestamp for verified. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "Consulting services" ], "status": "pending_verification", "verifiedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/pause" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/pause", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/pause failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # Resume webhook deliveries **POST** `/v1/webhooks/{webhookId}/resume` Resume deliveries for the addressed webhook. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/resume](https://docs.nqd.app/v1/reference/webhooks/resume) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data.name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data.destination` | `string` | Yes | No | destination for this webhook. | `"https://example.com/hooks/nqd"` | | `data.events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["Consulting services"]` | | `data.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending_verification", "active", "paused", "deleted") | `"pending_verification"` | | `data.verifiedAt` | `string` | Yes | Yes | ISO 8601 timestamp for verified. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "Consulting services" ], "status": "pending_verification", "verifiedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/resume" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/resume", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/resume failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # Rotate webhook signing credentials **POST** `/v1/webhooks/{webhookId}/rotate` Rotate signing credentials for the addressed webhook. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/rotate](https://docs.nqd.app/v1/reference/webhooks/rotate) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `overlapSeconds` | `number` | No | Yes | overlap seconds for this webhook. (minimum 60, maximum 86400) | `100` | ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.webhook` | `object` | Yes | No | webhook for this webhook. | — | | `data.webhook.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data.webhook.name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data.webhook.destination` | `string` | Yes | No | destination within webhook. | `"https://example.com/hooks/nqd"` | | `data.webhook.events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["Consulting services"]` | | `data.webhook.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending_verification", "active", "paused", "deleted") | `"pending_verification"` | | `data.webhook.verifiedAt` | `string` | Yes | Yes | ISO 8601 timestamp for verified. | `"2026-01-15T12:00:00.000Z"` | | `data.webhook.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.webhook.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | | `data.signingSecret` | `string` | Yes | No | signing secret for this webhook. | `"whsec_01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `data.rotation` | `object` | Yes | No | rotation for this webhook. | — | | `data.rotation.secretVersion` | `number` | Yes | No | secret version within rotation. | `100` | | `data.rotation.overlapSeconds` | `number` | Yes | No | overlap seconds within rotation. | `100` | | `data.rotation.previousSecretExpiresAt` | `string` | Yes | Yes | ISO 8601 timestamp for previous secret expires. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "webhook": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "Consulting services" ], "status": "pending_verification", "verifiedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" }, "signingSecret": "whsec_01JQ2T5Y5Q3R8W9N6M4K2H7P1A", "rotation": { "secretVersion": 100, "overlapSeconds": 100, "previousSecretExpiresAt": "2026-01-15T12:00:00.000Z" } } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/rotate" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/rotate", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/rotate failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # Send a test webhook delivery **POST** `/v1/webhooks/{webhookId}/test` Send a test delivery for the addressed webhook. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/test](https://docs.nqd.app/v1/reference/webhooks/test) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.accepted` | `boolean` | Yes | No | accepted for this webhook. | `true` | | `data.status` | `string` | Yes | No | Current status of the record or operation. | `"active"` | ```json { "data": { "accepted": true, "status": "active" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/test" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/test", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/test failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # Verify webhook **POST** `/v1/webhooks/{webhookId}/verify` Verify the addressed webhook. - Canonical URL: [https://docs.nqd.app/v1/reference/webhooks/verify](https://docs.nqd.app/v1/reference/webhooks/verify) - Scope: workspace ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer workspace API key. | `"Bearer $NQD_API_KEY"` | | `workspace-id` | `string` | Yes | No | Workspace scope for the request. Required for workspace operations and must belong to the authenticated identity. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ## Path parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `webhookId` | `string` | Yes | No | An opaque webhook resource identifier. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | ## Query parameters This operation has no query parameters. ## Request body The request body is an object with no documented fields. ```json {} ``` ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.id` | `string` | Yes | No | Opaque identifier for this resource or reference. (Minimum length: 1 character., Maximum length: 128 characters.) | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1Y"` | | `data.name` | `string` | Yes | No | Display name of the record. (Minimum length: 1 character., Maximum length: 120 characters.) | `"NQD record"` | | `data.destination` | `string` | Yes | No | destination for this webhook. | `"https://example.com/hooks/nqd"` | | `data.events` | `string[]` | Yes | No | Event names delivered by the webhook. (at least 1 items, at most 150 items) | `["Consulting services"]` | | `data.status` | `string` | Yes | No | Current status of the record or operation. (Allowed values: "pending_verification", "active", "paused", "deleted") | `"pending_verification"` | | `data.verifiedAt` | `string` | Yes | Yes | ISO 8601 timestamp for verified. | `"2026-01-15T12:00:00.000Z"` | | `data.createdAt` | `string` | Yes | No | ISO 8601 timestamp for the authored or payment event. Recurring records preserve their scheduled occurrence. | `"2026-01-15T12:00:00.000Z"` | | `data.updatedAt` | `string` | Yes | Yes | Timestamp used for stale-edit protection. Preserve the server value when updating. | `"2026-01-15T12:00:00.000Z"` | ```json { "data": { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1Y", "name": "NQD record", "destination": "https://example.com/hooks/nqd", "events": [ "Consulting services" ], "status": "pending_verification", "verifiedAt": "2026-01-15T12:00:00.000Z", "createdAt": "2026-01-15T12:00:00.000Z", "updatedAt": "2026-01-15T12:00:00.000Z" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/verify" \ -H "Authorization: Bearer $NQD_API_KEY" \ -H "Workspace-Id: $NQD_WORKSPACE_ID" \ -H "Content-Type: application/json" \ --data '{}' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/verify", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_API_KEY")}`, "Workspace-Id": requiredEnv("NQD_WORKSPACE_ID"), "Content-Type": "application/json", }, body: JSON.stringify({}), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/webhooks/01JQ2T5Y5Q3R8W9N6M4K2H7P1Y/verify failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - Inspect webhook state and delivery attempts through the related resources. --- # List workspaces available to the current identity **GET** `/v1/workspaces` List workspaces available to the current identity. - Canonical URL: [https://docs.nqd.app/v1/reference/workspaces/list](https://docs.nqd.app/v1/reference/workspaces/list) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `filter[id]` | `string` | No | No | Filter workspaces by id. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `filter[name]` | `string` | No | No | Filter workspaces by name. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.example"` | | `filter[role]` | `string` | No | No | Filter workspaces by role. Use operator.value syntax. (eq, neq, in, is operators) | `"eq.owner"` | | `select` | `string` | No | No | Comma-separated fields. Select a declared relation with relation(field,field). (declared fields and relations only) | `"id,name"` | | `order` | `string` | No | No | Order by field.asc or field.desc. Repeat fields with commas. (repeat fields separated by commas) | `"id.asc,name.asc"` | | `limit` | `integer` | No | No | Maximum records returned. Defaults to 25. (1 to 1000) | `25` | | `cursor` | `string` | No | No | Opaque continuation cursor returned by the previous page. | `"opaque-cursor"` | | `count` | `string` | No | No | Request an exact count. This may cost more than a normal page. (exact) | `"exact"` | ## Query contract Use the query parameters above. Default limit: 25. Maximum limit: 1000. Supported query errors: `invalid_input`, `query_invalid`, `unauthenticated`, `not_found`, `forbidden`, `plan_limit`, `conflict`, `rate_limited`, `request_quota`, `unavailable`, `internal_error`. ## Request body This operation does not accept a JSON request body. ## Responses ### 200 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object[]` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data[].id` | `string` | Yes | No | Opaque identifier for this resource or reference. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | | `data[].name` | `string` | Yes | No | Display name of the record. | `"Acme workspace"` | | `data[].role` | `string` | Yes | No | Role assigned to the identity in the workspace. (Allowed values: "owner", "admin", "member") | `"owner"` | | `page` | `object` | Yes | No | Pagination metadata for the returned records, or the current page number when this endpoint uses numbered pages. | — | | `page.limit` | `number` | Yes | No | Maximum number of records to return for this page. | `1` | | `page.hasMore` | `boolean` | Yes | No | Whether another page is available. | `false` | | `page.nextCursor` | `string` | Yes | Yes | Opaque cursor for the next page, or null when there is no next page. | `null` | | `page.total` | `number` | No | Yes | Total number of records that match the request. | `1` | ```json { "data": [ { "id": "01JQ2T5Y5Q3R8W9N6M4K2H7P1A", "name": "Acme workspace", "role": "owner" } ], "page": { "limit": 1, "hasMore": false, "nextCursor": null } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request GET "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/workspaces" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/workspaces", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "GET", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, }, }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `GET /v1/workspaces failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. --- # Create a workspace **POST** `/v1/workspaces` Create workspace from the submitted fields. - Canonical URL: [https://docs.nqd.app/v1/reference/workspaces/create](https://docs.nqd.app/v1/reference/workspaces/create) - Scope: identity ## Request headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `authorization` | `string` | Yes | No | Bearer access token returned by the authentication service. | `"Bearer $NQD_ACCESS_TOKEN"` | ## Path parameters This operation has no path parameters. ## Query parameters This operation has no query parameters. ## Request body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Acme workspace"` | | `country` | `string` | Yes | No | country for this workspace. (Minimum length: 1 character., Maximum length: 255 characters.) | `"SA"` | | `email` | `string` | Yes | Yes | Email address associated with the identity. (Maximum length: 255 characters.) | `"owner@example.com"` | | `phone` | `string` | Yes | Yes | phone for this workspace. (Maximum length: 255 characters.) | `"+966500000000"` | | `officialName` | `string` | Yes | Yes | official name for this workspace. (Maximum length: 255 characters.) | `"Consulting services"` | | `tradeName` | `string` | Yes | Yes | trade name for this workspace. (Maximum length: 255 characters.) | `"Consulting services"` | | `registrationNumber` | `string` | Yes | Yes | registration number for this workspace. (Maximum length: 255 characters.) | `"CR-0001234567"` | | `taxId` | `string` | Yes | Yes | ID of the related tax. (Maximum length: 255 characters.) | `"100.00"` | | `city` | `string` | Yes | Yes | city for this workspace. (Maximum length: 255 characters.) | `"Riyadh"` | | `address` | `string` | Yes | Yes | address for this workspace. (Maximum length: 255 characters.) | `"King Fahd Road"` | | `state` | `string` | Yes | Yes | Current state of the record or operation. (Maximum length: 255 characters.) | `"Riyadh"` | | `zip` | `string` | Yes | Yes | zip for this workspace. (Maximum length: 255 characters.) | `"Consulting services"` | | `currencyCode` | `string` | Yes | No | currency code for this workspace. (Minimum length: 1 character., Maximum length: 255 characters.) | `"SAR"` | | `payables` | `object[]` | No | Yes | payables for this workspace. | — | | `payables[].name` | `string` | Yes | No | Display name of the resource. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Acme workspace"` | | `payables[].recipient` | `string` | Yes | No | recipient within payables. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Consulting services"` | | `payables[].recipientType` | `string` | Yes | No | recipient type within payables. (Allowed values: "company", "individual", "government") | `"company"` | | `payables[].kind` | `string` | Yes | No | kind within payables. (Allowed values: "percentage", "fixed") | `"percentage"` | | `payables[].value` | `string` | Yes | No | Value returned by the operation. (Minimum length: 1 character., Maximum length: 128 characters.) | `"100.00"` | | `payables[].purpose` | `string` | Yes | No | purpose within payables. (Allowed values: "vat", "zakah", "custom") | `"vat"` | | `bank` | `object` | Yes | No | bank for this workspace. | — | | `bank.label` | `string` | Yes | No | Human-readable label for the value. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Operating account"` | | `bank.bankName` | `string` | Yes | No | bank name within bank. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD Bank"` | | `bank.accountName` | `string` | Yes | No | account name within bank. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Operating account"` | | `bank.accountNumber` | `string` | Yes | No | account number within bank. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Consulting services"` | | `bank.iban` | `string` | Yes | No | iban within bank. | `"SA0380000000608010167519"` | | `banks` | `object[]` | No | Yes | banks for this workspace. | — | | `banks[].label` | `string` | Yes | No | Human-readable label for the value. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Operating account"` | | `banks[].bankName` | `string` | Yes | No | bank name within banks. (Minimum length: 1 character., Maximum length: 255 characters.) | `"NQD Bank"` | | `banks[].accountName` | `string` | Yes | No | account name within banks. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Operating account"` | | `banks[].accountNumber` | `string` | Yes | No | account number within banks. (Minimum length: 1 character., Maximum length: 255 characters.) | `"Consulting services"` | | `banks[].iban` | `string` | Yes | No | iban within banks. | `"SA0380000000608010167519"` | | `fiscalStart` | `string` | Yes | Yes | fiscal start for this workspace. | `"2026-01-01"` | | `submissionId` | `string` | Yes | No | ID of the related submission. (Minimum length: 1 character., Maximum length: 255 characters.) | `"550e8400-e29b-41d4-a716-446655440000"` | ```json { "name": "Acme workspace", "country": "SA", "email": "owner@example.com", "phone": "+966500000000", "officialName": "Consulting services", "tradeName": "Consulting services", "registrationNumber": "CR-0001234567", "taxId": "100.00", "city": "Riyadh", "address": "King Fahd Road", "state": "Riyadh", "zip": "Consulting services", "currencyCode": "SAR", "bank": { "label": "Operating account", "bankName": "NQD Bank", "accountName": "Operating account", "accountNumber": "Consulting services", "iban": "SA0380000000608010167519" }, "fiscalStart": "2026-01-01", "submissionId": "550e8400-e29b-41d4-a716-446655440000" } ``` ## Responses ### 201 — Success Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `data` | `object` | Yes | No | Returned records. Collections and batches use an array; single records use an object. | — | | `data.workspaceId` | `string` | Yes | No | ID of the workspace that owns the resource. | `"01JQ2T5Y5Q3R8W9N6M4K2H7P1A"` | ```json { "data": { "workspaceId": "01JQ2T5Y5Q3R8W9N6M4K2H7P1A" } } ``` ### 400 — Invalid request Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"invalid_input"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The request could not be validated."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `[]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"invalid_request"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "invalid_input", "message": "The request could not be validated.", "requestId": "550e8400-e29b-41d4-a716-446655440000", "details": { "issues": [ { "path": [], "reason": "invalid_request" } ] } } } ``` ### 401 — Authentication required Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `www-authenticate` | `string` | Yes | No | Authentication challenge returned when credentials are missing or invalid. | `"Bearer"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unauthenticated"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Authentication required"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unauthenticated", "message": "Authentication required", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 403 — Access denied Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"forbidden"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"The authenticated identity cannot access this resource."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "forbidden", "message": "The authenticated identity cannot access this resource.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 404 — Resource not found Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"not_found"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource not found"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "not_found", "message": "Resource not found", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 409 — Resource conflict Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"conflict"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Resource conflict"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "conflict", "message": "Resource conflict", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 429 — Request limit reached Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `retry-after` | `string` | Yes | No | Seconds to wait before retrying a rate-limited request. | `"60"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"rate_limited"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Too many requests. Try again later."` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "rate_limited", "message": "Too many requests. Try again later.", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 500 — Internal server error Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"internal_error"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Internal server error"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "internal_error", "message": "Internal server error", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ### 503 — Service temporarily unavailable Response headers | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `x-request-id` | `string` | Yes | No | Correlation identifier returned with every response for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | Response body | Field | Type | Required | Nullable | Description | Example | | --- | --- | --- | --- | --- | --- | | `error` | `object` | Yes | No | Error details returned for a failed request. | — | | `error.code` | `string` | Yes | No | Stable machine-readable error or resource code. | `"unavailable"` | | `error.message` | `string` | Yes | No | Human-readable explanation of the result or error. | `"Service temporarily unavailable"` | | `error.requestId` | `string` | Yes | No | Correlation identifier for support and request tracing. | `"550e8400-e29b-41d4-a716-446655440000"` | | `error.details` | `object` | No | Yes | Additional structured details about the result or error. | — | | `error.details.issues` | `object[]` | Yes | No | Structured field issues returned when request validation fails. | — | | `error.details.issues[].path` | `string \| number[]` | Yes | No | Field path where the validation issue occurred. Alternatives: string alternative 1, number alternative 2. | `["Consulting services"]` | | `error.details.issues[].reason` | `string` | Yes | No | Machine-readable reason for the validation issue. (Allowed values: "expected_type", "required", "unexpected_property", "invalid_value", "invalid_json", "invalid_query", "unsupported_media_type", "body_too_large", "body_timeout", "conflicting_scope", "missing_header", "concurrency_required", "invalid_resource_id", "invalid_request") | `"expected_type"` | | `error.details.issues[].code` | `string` | No | Yes | Stable machine-readable error or resource code. | `"invalid_input"` | ```json { "error": { "code": "unavailable", "message": "Service temporarily unavailable", "requestId": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## cURL ```bash curl --include --fail-with-body --request POST "${NQD_API_URL:-http://api.nqd.localhost:1335}/v1/workspaces" \ -H "Authorization: Bearer $NQD_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data '{ "name": "Acme workspace", "country": "SA", "email": "owner@example.com", "phone": "+966500000000", "officialName": "Consulting services", "tradeName": "Consulting services", "registrationNumber": "CR-0001234567", "taxId": "100.00", "city": "Riyadh", "address": "King Fahd Road", "state": "Riyadh", "zip": "Consulting services", "currencyCode": "SAR", "bank": { "label": "Operating account", "bankName": "NQD Bank", "accountName": "Operating account", "accountNumber": "Consulting services", "iban": "SA0380000000608010167519" }, "fiscalStart": "2026-01-01", "submissionId": "550e8400-e29b-41d4-a716-446655440000" }' ``` ## Node.js ```js const env = process.env; const requiredEnv = (name) => { const value = env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const url = new URL("/v1/workspaces", env.NQD_API_URL ?? "http://api.nqd.localhost:1335"); const response = await fetch(url, { method: "POST", headers: { Authorization: `Bearer ${requiredEnv("NQD_ACCESS_TOKEN")}`, "Content-Type": "application/json", }, body: JSON.stringify({ "name": "Acme workspace", "country": "SA", "email": "owner@example.com", "phone": "+966500000000", "officialName": "Consulting services", "tradeName": "Consulting services", "registrationNumber": "CR-0001234567", "taxId": "100.00", "city": "Riyadh", "address": "King Fahd Road", "state": "Riyadh", "zip": "Consulting services", "currencyCode": "SAR", "bank": { "label": "Operating account", "bankName": "NQD Bank", "accountName": "Operating account", "accountNumber": "Consulting services", "iban": "SA0380000000608010167519" }, "fiscalStart": "2026-01-01", "submissionId": "550e8400-e29b-41d4-a716-446655440000" }), }); const requestId = response.headers.get("x-request-id"); const retryAfter = response.headers.get("retry-after"); const text = response.status === 204 ? "" : await response.text(); let payload; try { payload = text ? JSON.parse(text) : undefined; } catch { payload = text ? { error: { message: text } } : undefined; } if (!response.ok) { const error = payload?.error ?? {}; throw Object.assign(new Error(error.message ?? `POST /v1/workspaces failed`), { status: response.status, code: error.code ?? "request_failed", details: error.details, requestId: error.requestId ?? requestId, retryAfter }); } console.log({ status: response.status, requestId, body: payload }); ``` ## Errors Errors return `error.code`, `error.message`, and `error.requestId`. Invalid input may include safe `error.details.issues` field paths. Keep the request ID when reporting a failure. Retry only when this endpoint documents a transient 429 or 503 response, and honor `Retry-After` when present. ## Notes - This operation does not use a workspace scope. ---