Comment utiliser l'API Bytedoc depuis FileMaker Pro / FileMaker Cloud
- FileMaker Pro 16+ ou FileMaker Cloud
- Un compte Bytedoc avec une cle API
- Aucun plugin requis — tout est natif via Insert from URL
| Bytedoc | FileMaker equivalent |
|---|---|
| Template | Un modele de document (PDF form, HTML, DOCX) stocke sur le serveur |
| Document | Le resultat genere apres remplissage d'un template |
| API Key | Cle d'authentification (comme un mot de passe pour l'API) |
| Fill | Remplir un formulaire PDF existant |
| Generate | Generer un PDF a partir d'un template HTML |
| Webhook | Notification automatique quand un document est pret |
# --- Configuration ---
Set Variable [ $apiKey ; Value: GetValue ( Settings::APIKey ; 1 ) ]
Set Variable [ $baseUrl ; Value: "https://api.bytedoc.dev/v1" ]
Set Variable [ $templateId ; Value: Invoices::TemplateID ]
# --- Construire le JSON ---
Set Variable [ $json ; Value:
JSONSetElement ( "{}" ;
["template_id" ; $templateId ; JSONString] ;
["data.client_name" ; Clients::Name ; JSONString] ;
["data.client_address" ; Clients::Address ; JSONString] ;
["data.invoice_number" ; Invoices::Number ; JSONString] ;
["data.invoice_date" ; Invoices::Date ; JSONString] ;
["data.total" ; Invoices::Total ; JSONString] ;
["options.flatten" ; True ; JSONBoolean] ;
["options.filename" ; "facture-" & Invoices::Number & ".pdf" ; JSONString]
)
]
# --- Appel API ---
Set Variable [ $url ; Value: $baseUrl & "/documents/fill" ]
Insert from URL [ Select ; With dialog: Off ;
Target: $response ;
$url ;
cURL options:
"--request POST" &
" --header \"Authorization: Bearer " & $apiKey & "\"" &
" --header \"Content-Type: application/json\"" &
" --data @$json"
]
# --- Verifier le resultat ---
If [ Get(LastError) = 0 ]
Set Variable [ $docId ; Value: JSONGetElement ( $response ; "id" ) ]
Set Variable [ $downloadUrl ; Value: JSONGetElement ( $response ; "download_url" ) ]
# --- Telecharger le PDF dans un champ container ---
Insert from URL [ Select ; With dialog: Off ;
Target: Invoices::PDF_File ;
$downloadUrl ;
cURL options:
"--header \"Authorization: Bearer " & $apiKey & "\""
]
Set Field [ Invoices::DocumentID ; $docId ]
Set Field [ Invoices::Status ; "Genere" ]
Else
Show Custom Dialog [ "Erreur API" ;
"Code: " & Get(LastError) & ¶ &
"Detail: " & Get(LastExternalErrorDetail)
]
End If
# --- Configuration ---
Set Variable [ $apiKey ; Value: GetValue ( Settings::APIKey ; 1 ) ]
Set Variable [ $baseUrl ; Value: "https://api.bytedoc.dev/v1" ]
Set Variable [ $templateId ; Value: Settings::InvoiceTemplateID ]
# --- Construire le tableau d'articles ---
Set Variable [ $items ; Value: "[]" ]
Go to Related Record [ From table: "InvoiceLines" ; Using layout: "InvoiceLines" ]
Go to Record/Request/Page [ First ]
Loop
Set Variable [ $item ; Value:
JSONSetElement ( "{}" ;
["description" ; InvoiceLines::Description ; JSONString] ;
["quantity" ; InvoiceLines::Quantity ; JSONNumber] ;
["unit_price" ; InvoiceLines::UnitPrice ; JSONNumber] ;
["line_total" ; InvoiceLines::LineTotal ; JSONNumber]
)
]
Set Variable [ $items ; Value: JSONSetElement ( $items ; "[" & (Get(RecordNumber) - 1) & "]" ; $item ; JSONObject ) ]
Go to Record/Request/Page [ Next ; Exit after last: On ]
End Loop
# --- JSON complet ---
Set Variable [ $json ; Value:
JSONSetElement ( "{}" ;
["template_id" ; $templateId ; JSONString] ;
["data.company.name" ; Settings::CompanyName ; JSONString] ;
["data.company.address" ; Settings::CompanyAddress ; JSONString] ;
["data.company.siret" ; Settings::CompanySIRET ; JSONString] ;
["data.client.name" ; Clients::Name ; JSONString] ;
["data.client.address" ; Clients::Address ; JSONString] ;
["data.client.email" ; Clients::Email ; JSONString] ;
["data.invoice_number" ; Invoices::Number ; JSONString] ;
["data.invoice_date" ; Invoices::Date ; JSONString] ;
["data.due_date" ; Invoices::DueDate ; JSONString] ;
["data.items" ; $items ; JSONArray] ;
["data.subtotal" ; Invoices::Subtotal ; JSONNumber] ;
["data.tax_rate" ; Invoices::TaxRate ; JSONNumber] ;
["data.tax_amount" ; Invoices::TaxAmount ; JSONNumber] ;
["data.total" ; Invoices::Total ; JSONNumber] ;
["options.format" ; "A4" ; JSONString] ;
["options.filename" ; "facture-" & Invoices::Number & ".pdf" ; JSONString]
)
]
# --- Appel API ---
Set Variable [ $url ; Value: $baseUrl & "/documents/generate" ]
Insert from URL [ Select ; With dialog: Off ;
Target: $response ;
$url ;
cURL options:
"--request POST" &
" --header \"Authorization: Bearer " & $apiKey & "\"" &
" --header \"Content-Type: application/json\"" &
" --data @$json"
]
# --- Telecharger le resultat ---
If [ Get(LastError) = 0 ]
Set Variable [ $downloadUrl ; Value: JSONGetElement ( $response ; "download_url" ) ]
Insert from URL [ Select ; With dialog: Off ;
Target: Invoices::PDF_File ;
$downloadUrl ;
cURL options:
"--header \"Authorization: Bearer " & $apiKey & "\""
]
Set Field [ Invoices::DocumentID ; JSONGetElement ( $response ; "id" ) ]
Set Field [ Invoices::Status ; "Genere" ]
Else
Show Custom Dialog [ "Erreur API" ;
"Code: " & Get(LastError) & ¶ &
"Detail: " & Get(LastExternalErrorDetail)
]
End If
# --- Configuration ---
Set Variable [ $apiKey ; Value: GetValue ( Settings::APIKey ; 1 ) ]
Set Variable [ $baseUrl ; Value: "https://api.bytedoc.dev/v1" ]
# --- Appel API ---
Insert from URL [ Select ; With dialog: Off ;
Target: $response ;
$baseUrl & "/templates" ;
cURL options:
"--header \"Authorization: Bearer " & $apiKey & "\""
]
# --- Parser la reponse ---
If [ Get(LastError) = 0 ]
Set Variable [ $data ; Value: JSONGetElement ( $response ; "data" ) ]
Set Variable [ $count ; Value: ValueCount ( JSONListKeys ( $data ; "" ) ) ]
Set Variable [ $i ; Value: 0 ]
Loop
Exit Loop If [ $i >= $count ]
Set Variable [ $template ; Value: JSONGetElement ( $data ; "[" & $i & "]" ) ]
Set Variable [ $id ; Value: JSONGetElement ( $template ; "id" ) ]
Set Variable [ $name ; Value: JSONGetElement ( $template ; "name" ) ]
Set Variable [ $type ; Value: JSONGetElement ( $template ; "type" ) ]
# Creer ou mettre a jour l'enregistrement template
New Record/Request
Set Field [ Templates::ID ; $id ]
Set Field [ Templates::Name ; $name ]
Set Field [ Templates::Type ; $type ]
Commit Records/Requests
Set Variable [ $i ; Value: $i + 1 ]
End Loop
End If
# --- Configuration ---
Set Variable [ $apiKey ; Value: GetValue ( Settings::APIKey ; 1 ) ]
Set Variable [ $baseUrl ; Value: "https://api.bytedoc.dev/v1" ]
# --- Exporter le PDF du champ container ---
Set Variable [ $tempPath ; Value: Get(TemporaryPath) & "upload.pdf" ]
Export Field Contents [ Templates::SourcePDF ; "$tempPath" ]
# --- Upload multipart ---
Set Variable [ $url ; Value: $baseUrl & "/templates/from-pdf" ]
Insert from URL [ Select ; With dialog: Off ;
Target: $response ;
$url ;
cURL options:
"--request POST" &
" --header \"Authorization: Bearer " & $apiKey & "\"" &
" --form \"file=@" & $tempPath & "\"" &
" --form \"name=" & Templates::Name & "\""
]
# --- Parser la reponse ---
If [ Get(LastError) = 0 ]
Set Variable [ $templateId ; Value: JSONGetElement ( $response ; "id" ) ]
Set Variable [ $fieldsCount ; Value: JSONGetElement ( $response ; "fields_count" ) ]
Set Field [ Templates::BytedocID ; $templateId ]
Set Field [ Templates::FieldsCount ; $fieldsCount ]
Set Field [ Templates::Status ; "Processing" ]
Show Custom Dialog [ "Succes" ;
"Template cree: " & $templateId & ¶ &
"Champs detectes: " & $fieldsCount & ¶ & ¶ &
"Le template est en cours de traitement par l'IA." & ¶ &
"Verifiez le statut dans quelques secondes."
]
Else
Show Custom Dialog [ "Erreur API" ;
"Code: " & Get(LastError) & ¶ &
"Detail: " & Get(LastExternalErrorDetail)
]
End If
Creez une table Settings avec un seul enregistrement :
| Champ | Type | Description |
|---|---|---|
| APIKey | Texte | Votre cle pk_live_xxx |
| BaseURL | Texte | https://api.bytedoc.dev/v1 |
| InvoiceTemplateID | Texte | ID du template de facture |
Toujours verifier apres chaque Insert from URL :
If [ Get(LastError) <> 0 ]
# Erreur reseau ou FileMaker
Set Variable [ $fmError ; Value: Get(LastError) ]
Set Variable [ $detail ; Value: Get(LastExternalErrorDetail) ]
# Logger dans une table Logs
End If
# Verifier aussi les erreurs API
If [ not IsEmpty ( JSONGetElement ( $response ; "error.code" ) ) ]
Set Variable [ $errorCode ; Value: JSONGetElement ( $response ; "error.code" ) ]
Set Variable [ $errorMsg ; Value: JSONGetElement ( $response ; "error.message" ) ]
# USAGE_LIMIT_EXCEEDED → afficher un message
# UNAUTHORIZED → verifier la cle API
# TEMPLATE_NOT_FOUND → verifier l'ID du template
End If
| Plateforme | Support | Notes |
|---|---|---|
| FileMaker Pro 16+ | Oui | Insert from URL avec cURL |
| FileMaker Pro 19+ | Oui | Meilleur support JSON natif |
| FileMaker Server | Oui | Scripts cote serveur (PSOS) |
| FileMaker Cloud | Oui | Fonctionne sans modification |
| FileMaker Go | Oui | iOS/iPadOS, meme syntaxe |
| FileMaker WebDirect | Attention | Insert from URL limite — utiliser un script cote serveur via PSOS |
- Ne jamais coder la cle API en dur dans les scripts — utilisez la table Settings
- Loggez chaque appel API dans une table dediee pour le debugging
- Utilisez des scripts cote serveur (PSOS) pour les operations longues (Generate PDF)
- Testez d'abord avec une cle
pk_test_avant de passer en production - Gerez le timeout : ajoutez
--max-time 30aux options cURL pour les generations PDF