Atelier Sage
Mohammed MEZOUGH
13 avril 2026
Support privé — réservé aux participants invités.
Toute reproduction, redistribution ou utilisation commerciale sans autorisation écrite est interdite.
© Mohammed MEZOUGH. All rights reserved.
Sage Intacct propose une API REST pour connecter vos applications à ses données, fonctions et flux de travail.
Vos appels passent par HTTP, les payloads sont en JSON, et l'accès est protégé par OAuth 2.0.
Ce qu'on verra aujourd'hui :
© Mohammed MEZOUGH. All rights reserved.
© Mohammed MEZOUGH. All rights reserved.
Quick Start · Portail développeur · Société Intacct
https://company.local si pas d'URL de callback réelle),
mot de passe licence Web Services (Sender ID password),
Client Scope (Production ou Non-production — non modifiable après création).À conserver : Client ID · Client Secret · scope client.
Doc : Get started
Atelier : configuration portail en direct (écran partagé).
© Mohammed MEZOUGH. All rights reserved.
Le portail fournit l'application OAuth — dans la société, on active l'API et on autorise qui peut l'appeler (prérequis du token ch. 2).
À retenir : copier le Client ID et l'ID utilisateur WS à l'identique (sensible à la casse) — une variante empêche le token même si le secret est correct.
Atelier : même parcours Intacct en direct (écran partagé).
© Mohammed MEZOUGH. All rights reserved.
OAuth 2.0 · Client Credentials & Authorization Code
Ce flux sert aux accès machine à machine, sans interaction utilisateur.
Obtenir un jeton
Envoyer une requête POST vers oauth2/token avec un corps form-urlencoded.
client_credentials.webservice@company ou webservice@company|entity.À retenir : l'ID client doit être lié à un utilisateur Web Services (voir ch. 1). La réponse contient un access_token et un refresh_token (JWT) ; la durée est indiquée par expires_in (souvent 21600 s, soit 6 h).
Note : le suffixe |entity est optionnel. Vous choisissez le périmètre du jeton à la demande : top level ou entité uniquement.
Doc : OAuth 2.0
© Mohammed MEZOUGH. All rights reserved.
Dans Postman, exécuter la requête Get Token (Client Credentials).
POST /oauth2/token
Corps
grant_type=client_credentials
client_id=xxx.app.sage.com
client_secret=••••••
username=webservice@company|entity
200 OK
Réponse
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 21600
}
Note : omettez |entity dans username pour un jeton top level. Corps en form-urlencoded (ou JSON selon la collection Postman).
Exemple Node : client-credentials.mjs
© Mohammed MEZOUGH. All rights reserved.
Ce flux sert lorsqu'un utilisateur réel se connecte via votre application (navigateur, mobile). Les appels API sont exécutés à son nom, et non via un compte Web Services.
Flux en 2 étapes
oauth2/authorize avec les paramètres requis en query string. Sage Intacct renvoie un code d'autorisation.oauth2/token (corps form-urlencoded) pour récupérer les jetons.À retenir : le code est à usage unique. Redirect URI en https (pas localhost) — même valeur à l'enregistrement de l'app, en étape 1 et en étape 2. Le client_secret ne doit jamais transiter côté navigateur.
Note : il n'y a pas de suffixe |entity dans ce flux. Le jeton est émis au niveau top level, ou sur l'entité par défaut de l'utilisateur si elle est définie dans Intacct.
© Mohammed MEZOUGH. All rights reserved.
Étape navigateur : construire l'URL d'autorisation avec les paramètres en query string.
GET /oauth2/authorize?response_type=code&client_id=xxx.app.sage.com&redirect_uri=https://app.example/callback&scope=offline_access
302 Redirect
Réponse · callback
https://app.example/callback
?code=AUTH_CODE_HERE
Note : Redirect URI = https (pas localhost) — même chaîne en étape 1 et 2. Après redirect, copier code depuis l'URL.
Exemple Node : authorization-code.mjs — les 2 étapes dans un fichier.
© Mohammed MEZOUGH. All rights reserved.
Étape serveur : dans Postman, exécuter Get Token (Authorization Code) avec un corps form-urlencoded.
POST /oauth2/token
Corps
grant_type=authorization_code
client_id=xxx.app.sage.com
client_secret=••••••
code=AUTH_CODE_HERE
redirect_uri=https://app.example/callback
200 OK
Réponse
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 21600
}
Démo : authorization-code.mjs (ouvrir URL → coller le code) ou Postman.
© Mohammed MEZOUGH. All rights reserved.
Dans une société multi-entités, le jeton fixe un contexte d'accès. Selon le flux utilisé, deux approches permettent de cibler les enregistrements d'une sous-entité.
Cibler une sous-entité
X-IA-API-Param-Entity à chaque requête API, avec l'ID entité (propriété company-config/entity.id, ex. CentralUS-35).|entity dans username (Client Credentials), ou paramètre location_id lors d'un POST oauth2/token avec grant_type=refresh_token.À retenir : avec Client Credentials, vous choisissez le périmètre à l'émission du jeton. Avec Authorization Code, le jeton est top level ou entité par défaut de l'utilisateur — le header permet ensuite de cibler une autre entité si le jeton est top level.
© Mohammed MEZOUGH. All rights reserved.
Jeton top level · cibler une entité par header ou par refresh.
GET /objects/vendor
Header · requête API
Authorization: Bearer <top_level_token>
X-IA-API-Param-Entity: CentralUS-35
POST /oauth2/token
Corps · refresh vers jeton entité
grant_type=refresh_token
client_id=xxx.app.sage.com
client_secret=••••••
refresh_token=eyJ...
location_id=CentralUS-35
Note : le refresh avec location_id renvoie un nouveau jeton utilisable pour les appels suivants, sans header entité à chaque requête.
Exemples Node :
entity-header.mjs
·
token-refresh-entity.mjs
© Mohammed MEZOUGH. All rights reserved.
Service Model · Champs et objets personnalisés
Le service Model retourne les champs et les relations d'une ressource — à consulter avant Query ou CRUD.
Requêtes types
Tous les appels sont des GET vers /services/core/model, avec Authorization: Bearer.
/services/core/model — définition courte de toutes les ressources.?name=company-config/department — modèle complet (<application>/<ressource>).?name=projects/task&version=v1 — modèle pour une version d'API.?version=v1&schema=true&type=workflow — tous les modèles d'un type (object, service, workflow).À retenir : objets custom platform-apps/nsp::<nom> · ?description=true pour les descriptions · schema true/false selon liste ou ressource unique.
Doc : Model (OpenAPI)
© Mohammed MEZOUGH. All rights reserved.
Avant Query ou CRUD sur les fournisseurs, on consulte le Model de accounts-payable/vendor.
GET /services/core/model?name=accounts-payable/vendor
200 OK
Réponse · extrait (sandbox)
{
"name": "accounts-payable/vendor",
"fields": [
{ "id": "id", "label": "Vendor ID" },
{ "id": "name", "label": "Name" },
{ "id": "status", "label": "Status" },
{ "id": "billingType", "label": "Billing type" }
]
}
Note : le Model complet liste types, nullabilité et relations. Le client du fil facture expose des champs nsp:: (slide suivante).
Exemple Node : vendor.mjs
© Mohammed MEZOUGH. All rights reserved.
Champs métier (UI) → préfixe nsp::. Exemple client Sage 100 sur accounts-receivable/customer — fil rouge CL0642.
nsp::SAGE100_DB, nsp::SAGE100_ID, …POST /services/core/query
Corps · client + champs Sage 100
{
"object": "accounts-receivable/customer",
"fields": [
"id", "name", "key",
"nsp::SAGE100_DB", "nsp::SAGE100_ID"
],
"filters": [{ "$eq": { "id": "CL0642" } }],
"start": 1,
"size": 1
}
200 OK
Réponse · sandbox
{
"ia::result": [{
"id": "CL0642",
"name": "Bague's en or modifié",
"key": "181",
"nsp::SAGE100_DB": "BIJOU",
"nsp::SAGE100_ID": "BAGUES"
}],
"ia::meta": { "totalCount": 1 }
}
À retenir : même règle pour Export et Composite.
Exemple Node : customer-nsp.mjs
© Mohammed MEZOUGH. All rights reserved.
Objets custom → platform-apps/nsp::{nom} (ex. platform-apps/nsp::partenaire sur le sandbox).
id, name, montant, …).object que pour le Model./objects/platform-apps/nsp::partenaire/{key}GET /services/core/model?name=platform-apps/nsp::partenaire&description=true
200 OK · Model (extrait)
Champs
{
"name": "platform-apps/nsp::partenaire",
"fields": [
{ "id": "id" },
{ "id": "name" },
{ "id": "montant" },
{ "id": "key", "readOnly": true }
]
}
À retenir : champs nsp:: sur objets standard (client) ≠ objets platform-apps/nsp:: · Query : POST /services/core/query avec "object": "platform-apps/nsp::partenaire" (ch. 4) · droits requis sur l'objet custom.
Exemples Node :
custom-object-partenaire.mjs
·
query-partenaire.mjs
© Mohammed MEZOUGH. All rights reserved.
Query · Export
Le service Query retourne les objets filtrés d'une société Sage Intacct.
Requête principale
POST /services/core/query — corps JSON.
accounts-payable/vendor ou platform-apps/nsp::<nom>vendor.id), agrégats (max:vendor.creditLimit)$eq, $in, $contains, …À retenir : consulter le Model pour les noms de champs valides.
Doc : Query service · Query (OpenAPI)
© Mohammed MEZOUGH. All rights reserved.
Affiner et parcourir de gros volumes.
[{"id": "asc"}]trueÀ retenir : pour très gros volumes, paginer avec Query ou utiliser Export / Bulk.
© Mohammed MEZOUGH. All rights reserved.
On filtre les fournisseurs actifs en open item — même logique que pour les factures plus loin.
POST /services/core/query
Corps
{
"object": "accounts-payable/vendor",
"fields": ["id", "name", "status", "href"],
"filters": [
{"$eq": {"status": "active"}},
{"$eq": {"billingType": "openItem"}}
],
"filterExpression": "1 and 2",
"orderBy": [{"id": "asc"}],
"start": 1,
"size": 100
}
200 OK
Réponse · extrait
{
"ia::result": [
{
"id": "FR0693",
"name": "SAGE",
"status": "active",
"href": "/objects/accounts-payable/vendor/1",
"billingType": "openItem"
},
{
"id": "VND-001",
"name": "Vendor 007 entity",
"status": "active",
"href": "/objects/accounts-payable/vendor/43",
"billingType": "openItem"
}
],
"ia::meta": {
"totalCount": 17,
"start": 1,
"pageSize": 100
}
}
À retenir : réponse JSON paginée — ici 17 fournisseurs sur le sandbox.
Exemple Node : vendors.mjs
© Mohammed MEZOUGH. All rights reserved.
Même service Query sur le fil facture : champs liés via customer.id et customer.name (équivalent de vendor.* côté AP).
POST /services/core/query
Corps
{
"object": "accounts-receivable/invoice",
"fields": [
"id", "invoiceNumber",
"customer.id", "customer.name",
"invoiceDate", "dueDate",
"totalTxnAmount", "state"
],
"filters": [{ "$gt": { "totalTxnAmount": "0" } }],
"orderBy": [{ "invoiceDate": "desc" }],
"start": 1,
"size": 100
}
200 OK
Réponse · extrait (sandbox)
{
"ia::result": [
{
"id": "69",
"invoiceNumber": "bm",
"customer.id": "CL0642",
"customer.name": "Bague's en or modifié",
"invoiceDate": "2026-05-22",
"dueDate": "2026-07-05",
"totalTxnAmount": "200.00"
}
],
"ia::meta": { "totalCount": 3, "start": 1, "pageSize": 100 }
}
Exemple Node : invoices.mjs
© Mohammed MEZOUGH. All rights reserved.
Le service Export produit un fichier à partir d'une requête filtrée.
Formats
POST /services/core/export — fileType + objet query.
csv, pdf, word, xml, xlsxÀ retenir : réponse = fichier téléchargeable.
Doc : Export (OpenAPI) — options du POST /services/core/export
© Mohammed MEZOUGH. All rights reserved.
Même filtres que Query, mais la réponse est un fichier (PDF, CSV, …) — pratique pour l'utilisateur métier.
POST /services/core/export
Corps
{
"fileType": "pdf",
"query": {
"object": "accounts-payable/vendor",
"fields": ["id", "name", "status", "href"],
"filters": [
{"$eq": {"status": "active"}},
{"$eq": {"billingType": "openItem"}}
],
"filterExpression": "1 and 2",
"orderBy": [{"id": "asc"}]
}
}
200 OK
Réponse · métadonnées (sandbox)
{
"status": 200,
"statusText": "OK",
"contentType": "application/pdf",
"sizeBytes": 8421,
"_note": "PDF binaire non affiché"
}
À retenir : pas de tableau ia::result — fichier binaire (PDF).
Exemple Node : vendors-pdf.mjs
© Mohammed MEZOUGH. All rights reserved.
GET · POST · PATCH · DELETE
Ressources : /objects/{application}/{object} et /.../{key} pour le détail.
ia::metaÀ retenir : exploration → GET liste ; extraction métier → Query · Authorization: Bearer sur chaque appel (ch. 2), non répété sur les exemples JSON.
Doc : OpenAPI — objet métier (ex. invoice, vendor)
© Mohammed MEZOUGH. All rights reserved.
La liste renvoie des références légères ; elle peut être vide avant la première création en sandbox.
GET /objects/accounts-receivable/invoice
200 OK
Réponse · extrait (sandbox)
{
"ia::result": [
{"key": "63", "id": "63", "href": "/objects/accounts-receivable/invoice/63"}
],
"ia::meta": {
"totalCount": 1,
"start": 1,
"pageSize": 100
}
}
Exemple Node : get-invoices-list.mjs
© Mohammed MEZOUGH. All rights reserved.
Avec la key de la liste, on charge la facture complète — client, montants et lignes.
GET /objects/accounts-receivable/invoice/67
200 OK
Réponse · extrait (sandbox)
{
"ia::result": {
"key": "67",
"invoiceDate": "2026-05-21",
"dueDate": "2026-07-15",
"referenceNumber": "PO-UPDATED-99",
"description": "Modifié par Atelier — en-tête facture",
"totalTxnAmount": "150.00",
"customer": { "id": "CL0642", "name": "Bague's en or modifié" },
"currency": { "baseCurrency": "EUR", "txnCurrency": "EUR" },
"lines": [{
"key": "137",
"txnAmount": "150.00",
"memo": "Ligne mise à jour — atelier",
"glAccount": { "id": "701000", "name": "Ventes de produits finis" },
"dimensions": {
"location": { "id": "DEMO_1", "name": "Entité 1" }
}
}]
}
}
Note : la key de ligne (137) sert au PATCH sur invoice-line.
Exemple Node : get-invoice-detail.mjs
© Mohammed MEZOUGH. All rights reserved.
POST /objects/{application}/{object} — corps JSON avec champs obligatoires et objets liés.
ia::result : id, key, href© Mohammed MEZOUGH. All rights reserved.
On crée une facture AR pour CL0642 — en-tête + une ligne, champs issus du Model atelier.
POST /objects/accounts-receivable/invoice
Corps · extrait
{
"customer": { "id": "CL0642" },
"invoiceDate": "2026-05-21",
"dueDate": "2026-06-20",
"referenceNumber": "PO-ATELIER-001",
"description": "Facture démo atelier REST API",
"lines": [{
"txnAmount": "100",
"glAccount": { "id": "701000" },
"memo": "Prestation atelier",
"dimensions": {
"customer": { "id": "CL0642" },
"location": { "id": "DEMO_1" }
}
}]
}
201 Created
Réponse (sandbox)
{
"ia::result": {
"key": "67",
"id": "67",
"href": "/objects/accounts-receivable/invoice/67"
},
"ia::meta": { "totalSuccess": 1, "totalError": 0 }
}
Model d'abord : invoiceDate, dueDate, referenceNumber, description — voir Model accounts-receivable/invoice.
Exemple Node : post-invoice.mjs
© Mohammed MEZOUGH. All rights reserved.
PATCH /objects/.../{key} — mise à jour partielle : champs absents = inchangés.
Succès : 200 OK. Champs modifiables : voir le Model · lignes de document : endpoints dédiés.
© Mohammed MEZOUGH. All rights reserved.
On ne renvoie que ce qui change — ici référence, description et échéance de la facture 67.
PATCH /objects/accounts-receivable/invoice/67
Corps
{
"referenceNumber": "PO-UPDATED-99",
"description": "Modifié par Atelier — en-tête facture",
"dueDate": "2026-07-15"
}
200 OK
Réponse (sandbox)
{
"ia::result": {
"key": "67",
"id": "67",
"href": "/objects/accounts-receivable/invoice/67"
}
}
À retenir : pas besoin de renvoyer tout l'objet — seuls les champs du corps sont mis à jour.
Exemple Node : patch-invoice.mjs
© Mohammed MEZOUGH. All rights reserved.
DELETE /objects/.../{key} — pas de corps.
Succès : 204 No Content.
Vérifier dépendances et règles métier avant suppression en production.
© Mohammed MEZOUGH. All rights reserved.
Une ligne se met à jour sur /objects/accounts-receivable/invoice-line/{key}, pas sur l'en-tête facture.
PATCH /objects/accounts-receivable/invoice-line/137
Corps
{
"txnAmount": "150.00",
"memo": "Ligne mise à jour — atelier"
}
200 OK
Réponse (sandbox)
{
"ia::result": {
"key": "137",
"id": "137",
"href": "/objects/accounts-receivable/invoice-line/137"
}
}
Exemple Node : patch-invoice-line.mjs
© Mohammed MEZOUGH. All rights reserved.
Nettoyage de la facture de démo — pas de corps, réponse 204 si tout va bien.
DELETE /objects/accounts-receivable/invoice/67
204 No Content
Réponse
(corps vide)
Exemple Node : delete-invoice.mjs
© Mohammed MEZOUGH. All rights reserved.
Batch · Bulk · Composite · Asynchrone
Éviter des centaines d'appels identiques : un tableau JSON, un seul POST — tout est traité tout de suite (même type d'objet, max 500).
/objects/.../bill/194,195,310Header : X-IA-API-Param-Transaction: true pour atomicité (rollback si un échec).
Doc : Batch, bulk & composite
© Mohammed MEZOUGH. All rights reserved.
Trois fournisseurs créés en une fois — utile pour des imports de taille moyenne.
POST /objects/accounts-payable/vendor
Corps · tableau
[
{ "id": "batchv1-…", "name": "Batch Vendor 1 …" },
{ "id": "batchv2-…", "name": "Batch Vendor 2 …" },
{ "id": "batchv3-…", "name": "Batch Vendor 3 …" }
]
200 OK
Réponse (sandbox)
{
"ia::result": [
{ "key": "48", "id": "batchv1-0521130212", "href": "/objects/accounts-payable/vendor/48" },
{ "key": "49", "id": "batchv2-0521130212", "href": "/objects/accounts-payable/vendor/49" },
{ "key": "50", "id": "batchv3-0521130212", "href": "/objects/accounts-payable/vendor/50" }
],
"ia::meta": { "totalCount": 3, "totalSuccess": 3, "totalError": 0 }
}
À retenir : totalSuccess / totalError dans ia::meta — ou 207 si succès et échecs mélangés.
Exemple Node : batch-post-vendors.mjs
© Mohammed MEZOUGH. All rights reserved.
Pour de très gros volumes : on dépose un fichier, Intacct traite en arrière-plan — on récupère un jobId, pas une attente bloquante.
POST /services/bulk/job/create — multipart/form-data (métadonnées + fichier JSON).
Partie ia::requestBody
{
"objectName": "accounts-payable/vendor",
"operation": "create",
"jobFile": "file",
"fileContentType": "json"
}
+ partie file (ex. fournisseurs)
[
{ "id": "bulkv…1", "name": "Bulk Vendor 1" },
{ "id": "bulkv…2", "name": "Bulk Vendor 2" }
]
Même syntaxe pour clients AR
[
{ "id": "bulkCL…1", "name": "Bulk Client 1" }
]
201 Created
Réponse (sandbox)
{
"ia::result": {
"jobId": "95884b67-fd9e-42ba-af94-b39dee3d53f1",
"statusURL": "/services/bulk/job/status?jobId=…"
}
}
file = tableau JSON · champs minimaux selon le Model de l’objet.
Doc : Batch, bulk & composite — section Bulk
Exemple Node : bulk-create-vendors.mjs
© Mohammed MEZOUGH. All rights reserved.
On interroge le job jusqu'à completed, puis on télécharge le fichier résultat (succès / erreurs par ligne).
GET /services/bulk/job/status?jobId=…&download=true
{
"ia::result": {
"jobId": "f426e9c9-130d-4a9f-9dae-3a3a2935f850",
"status": "completed",
"percentComplete": 100
}
}
À retenir : distinct du /services/core/async/job-status (header Prefer: respond-async).
Exemple Node : bulk-job-status.mjs
© Mohammed MEZOUGH. All rights reserved.
Un seul appel HTTP pour enchaîner plusieurs opérations — la réponse d'une étape peut alimenter la suivante (ex. créer une facture puis la relire).
POST /services/core/composite — tableau de sous-requêtes, exécutées dans l'ordre.
ia::result par sous-requête + ia::meta (totalSuccess, totalError)Idempotency-Key recommandé pour éviter les doublons.
Doc : Batch, bulk & composite — section Composite
© Mohammed MEZOUGH. All rights reserved.
Étape 1 : POST facture · étape 2 : GET la même facture avec la key renvoyée — sans second appel « à la main ».
POST /services/core/composite
Corps · extrait
[
{
"method": "POST",
"path": "/objects/accounts-receivable/invoice",
"body": {
"customer": { "id": "CL0642" },
"invoiceDate": "2026-05-21",
"dueDate": "2026-06-20",
"lines": [{ "txnAmount": "100", "glAccount": { "id": "701000" },
"dimensions": { "customer": { "id": "CL0642" }, "location": { "id": "DEMO_1" } } }]
},
"resultReference": "newInvoice"
},
{
"method": "GET",
"path": "/objects/accounts-receivable/invoice/@{newInvoice.key}"
}
]
200 OK
Réponse (sandbox)
{
"ia::result": [
{ "ia::status": 201, "ia::result": { "key": "75", "id": "75" } },
{ "ia::status": 200, "ia::result": {
"key": "75", "referenceNumber": "PO-COMP-…",
"customer": { "id": "CL0642", "name": "…" }
}}
],
"ia::meta": { "totalSuccess": 2, "totalError": 0 }
}
À retenir : resultReference + @{newInvoice.key} — on peut aussi enchaîner client → facture, si le tenant l'autorise.
Exemple Node : composite-invoice.mjs
© Mohammed MEZOUGH. All rights reserved.
Quand l'opération est longue : on ne bloque pas la connexion — Intacct répond tout de suite 202 avec un jobId à suivre.
Header Prefer: respond-async sur la requête métier (POST, PATCH, …).
Headers
Prefer: respond-async
Authorization: Bearer …
202 Accepted
ACK · extrait
{
"ia::result": {
"jobId": "NjQ2NTc2MzAzMNl1Ul9qVmd6M2t4M12pPdEJya2Jt65Y2dBQUFBQTE",
"state": "queued",
"queuedDateTime": "2025-11-11T00:47:12Z",
"href": "/services/core/async/job-status?jobId=…"
},
"ia::meta": { "totalCount": 1 }
}
Retry-After ~ 2 min · états : queued, inTransit, delivered, dead, … · Async URIs (ch. 1) pour webhooks.
Doc : Asynchronous requests
Exemple Node : async-prefer.mjs
© Mohammed MEZOUGH. All rights reserved.
Récapitulatif — le bon outil selon le besoin métier.
size max 4000jobId + téléchargement résultatresultReferencePrefer: respond-async · ACK 202 + job-status (≠ Bulk)À retenir : Bulk /services/bulk/job/status ≠ core async /services/core/async/job-status — même idée de suivi, services différents.
Volume / concurrence API → API volume & scaling — pas de détail en atelier.
© Mohammed MEZOUGH. All rights reserved.
Conversions · Dépôt · Références
Symptôme HTTP → première piste de vérification.
oauth2/token (ch. 2)ia::error{
"ia::result": {
"ia::error": {
"code": "invalidRequest",
"message": "A POST request requires a payload",
"errorId": "REST-1028"
}
},
"ia::meta": { "totalError": 1 }
}
À retenir : en atelier, Postman affiche le corps d'erreur — lire errorId + details, ne pas deviner.
© Mohammed MEZOUGH. All rights reserved.
Order Entry et Purchasing — POST sur la définition cible (pas le document source) ; lier la source via sourceDocument et les clés de ligne.
/objects/order-entry/document::Sales Return (ex. Sales Invoice → Sales Return)À retenir : Model + dossiers Postman Order Entry / Purchasing pour les payloads complets ; clés source depuis GET ou Query.
Purchasing — même mécanisme : PO → POST /objects/purchasing/document::Vendor Invoice · Document conversions
© Mohammed MEZOUGH. All rights reserved.
Sales Invoice → Sales Return — extrait doc Sage.
POST /objects/order-entry/document::Sales Return
Corps · extrait
{
"sourceDocument": { "key": "12920" },
"lines": [{
"sourceDocument": { "key": "12920" },
"sourceDocumentLine": { "key": "14468" },
"dimensions": { "item": { "id": "1" } },
"unitQuantity": "1",
"unitPrice": "1000"
}]
}
201 Created
Réponse · extrait
{
"ia::result": {
"key": "12922",
"id": "12922",
"href": "/objects/order-entry/document::Sales%20Return/12922"
},
"ia::meta": {
"totalSuccess": 1,
"totalError": 0
}
}
À retenir : champs en-tête complets (customer, dates, devises…) — voir Document conversions.
© Mohammed MEZOUGH. All rights reserved.
Démo Postman et exemples Node (dépôt public).
blob/ GitHubConfigurer lib/config.mjs (ou variables Postman) avant la démo live.
© Mohammed MEZOUGH. All rights reserved.
© Mohammed MEZOUGH. All rights reserved.
© Mohammed MEZOUGH. All rights reserved.