Skip to main content

Presentant FileMaker OData Webhooks Manager #

L’eina open-source, les decisions d’arquitectura i els set comportaments de l’API no documentats que absolutament ningú em va avisar #


Fa unes setmanes vaig escriure sobre com els webhooks OData de FileMaker Server 22.0.4 converteixen la plataforma en un ciutadà realment basat en esdeveniments — a l’estil de Stripe, a l’estil de GitHub, pròpiament modern. Encara ho crec. La capacitat és realment un punt d’inflexió.

Però després em vaig asseure per construir alguna cosa real a sobre. Un gestor de webhooks. Una eina que et permeti navegar per les teves bases de dades FileMaker, crear i editar webhooks visualment, provar-los sense tocar dades de producció i inspeccionar l’estat de cada entrega pendent.

El que vaig trobar en el procés va ser una bretxa — entre la característica existeix i la característica és realment utilitzable — que és més ampla del que deixa entreveure qualsevol documentació oficial.

Aquest és l’article de seguiment. El menys afalagador. El que, amb sort, estalvia un cap de setmana.


L’Eina: FMS-odata-webhooks #

Primer, deixa’m mostrar-te el que he construït, perquè és el context de tota la resta.

FMS-odata-webhooks és una aplicació web React que et proporciona una interfície visual per a l’API de webhooks OData de FileMaker. És de codi obert, llicenciada MIT i construïda per gestionar totes les peculiaritats descrites a continuació perquè no hagis de descobrir-les tu mateix.

Què fa #

Navegador de bases de dades — Connecta’t a qualsevol instància de FileMaker Server 22.0.4+ amb les teves credencials OData. L’aplicació llista les teves bases de dades disponibles, et permet seleccionar-ne una i exposa els metadats complets de taules i camps, incloses les anotacions de tipus específiques de FileMaker. Pots explorar el teu esquema abans d’escriure una sola línia de codi d’integració.

Gestor de webhooks — Una interfície CRUD completa per a la gestió de webhooks:

  • Crea webhooks amb selecció visual de camps des de l’esquema en viu
  • Configura expressions de filtre OData amb validació en temps real
  • Estableix capçaleres HTTP personalitzades (per a l’autenticació del receptor, metadates o encaminament)
  • Activa les notificacions de canvi d’esquema per webhook
  • Edita webhooks — que abstrau el patró d’esborrar+crear que requereix l’API (més sobre això a continuació)
  • Esborra webhooks amb confirmació
  • Invoca manualment qualsevol webhook contra IDs de registre específics per a proves

Panell d’operacions pendents (proper) — Cada webhook porta una cua pendingOperations[] d’esdeveniments que esperen ser lliurats o que han fallat. El proper panell exposarà aquesta cua directament a la interfície: tipus d’operació (ADD, UPDATE, DELETE, SCHEMA), estat de lliurament, codis d’error, missatges d’error i recompte de reintents. Aquesta informació està a la resposta de l’API però completament absent de la documentació oficial. Exposar-la està a la ruta, perquè és or per a la depuració.

Prova d’endpoints — Un conjunt d’utilitats de consola del navegador (window.FileMakerTests.*) per a l’exploració de l’API de baix nivell: comprovacions de connectivitat, validació completa d’endpoints a través de tots els mètodes HTTP, proves d’integració que creen i netegen webhooks reals.

Stack tecnològic #

React 18 + Vite, Tailwind CSS, components shadcn/ui. Sense backend, sense base de dades. Tot l’estat viu a FileMaker Server. En desenvolupament, Vite fa de proxy de /fmi/* al teu servidor i gestiona CORS. En producció, necessites nginx per fer el mateix — que és un dels comportaments no documentats tractats a continuació.

El codi està a github.com/fsans/FMS-odata-webhooks. Fork it, usa’l, obre issues.


Començar en cinc minuts #

git clone https://github.com/fsans/FMS-odata-webhooks.git
cd FMS-odata-webhooks
npm install
npm run dev

Obre http://localhost:5173. Abans de connectar, visita https://your-filemaker-server/fmi/odata/v4 al teu navegador i accepta l’avís de certificat SSL — això desbloqueja el proxy en mode desenvolupament. Introdueix l’amfitrió del teu servidor i les credencials OData, fes clic a Connect.

Això és tot. Estàs navegant pel teu esquema FileMaker i gestionant webhooks.


Les set coses que ningú em va dir #

Ara per la part que va costar més temps. Aquests no són casos límit. Són comportaments fonamentals de l’API de webhooks OData de FileMaker que trobaràs en qualsevol projecte d’integració seriós. Cap d’ells està documentat a la guia OData de Claris.

1. “Només POST” és un mite — el contracte real és mixt GET/POST #

La informació pública sobre aquesta API és escassa — gairebé nul·la. Una publicació mínima a Claris Community del personal tècnic de Claris, i breument el meu propi README, deien el mateix: totes les operacions de webhook són només POST.

Fals.

Segons la guia oficial OData de Claris i confirmat a través de proves sistemàtiques, el contracte HTTP real és:

EndpointMètodeNotes
Webhook.GetAllGETRetorna la llista completa
Webhook.Get(<id>)GET<id> al camí URL
Webhook.AddPOSTConfig al cos JSON
Webhook.Delete(<id>)POST<id> al camí URL
Webhook.Invoke(<id>)POST<id> al camí URL, rowIDs al cos

Els endpoints de lectura són GET. Els endpoints d’acció són POST. I el <id> és un argument de funció OData al camí URL — no un camp webhookID al cos JSON. Si et confons, obtens respostes HTTP 400 sense cap missatge d’error útil. L’aplicació gestiona això correctament; ho documento aquí perquè el trobaràs el moment que intentis cridar l’API directament.

  • ❌ PUT i PATCH no existeixen a cap endpoint de webhook.
  • ❌ L’estil REST DELETE /Webhook/<id> tampoc existeix. Usa POST /Webhook.Delete(<id>).

2. La trampa del camp id — i per què pot congelar el teu webhook permanentment #

Aquesta té una vora afilada.

La cadena en minúscules id és tractada com una paraula reservada internament pel motor OData de FileMaker. S’assigna a l’ID de registre intern de FileMaker. Si tens un camp a la teva taula també anomenat id, obtens una col·lisió de noms — i la col·lisió no falla simplement amb gràcia.

Aquí hi ha un error real del meu entorn de proves, capturat directament de la cua pendingOperations:

{
  "operation": "UPDATE",
  "rowIDs": [19972],
  "status": "NOT_SENT",
  "lastErrorCode": -1002,
  "lastErrorMessage": "Error: syntax error in URL at: 'id'",
  "sendAttempts": 36
}

FileMaker continua reintentant. Al meu entorn de proves sendAttempts va pujar passant desenes de milers sense resolució i la cua mai es va esvair per si sola — el webhook està efectivament congelat fins que l’esborris.

La solució:

  • Millor: canvia el nom del camp. ID (majúscules) no col·lisiona. Tampoc record_id, row_id, contact_id, o qualsevol cosa que no sigui la cadena exacta en minúscules id.
  • Solució ràpida: posa-la entre cometes a $select — usa "id" en lloc de id.
$select=first_name,last_name,"id"   ✅
$select=first_name,last_name,id     ❌ (error de sintaxi a l'URL)

L’aplicació valida les seleccions de camps i t’avisa si un camp anomenat id s’inclou sense cometes.

3. No PATCH, no PUT — cada edició és una eliminació #

Vols ajustar el filtre d’un webhook? Ajustar quins camps inclou? Canviar l’URL de callback?

No pots. No hi ha Webhook.Update. No hi ha PATCH. No hi ha cap edició suau de cap mena.

L’única manera de modificar un webhook és esborrar-lo i crear-ne un de nou. El nou webhook obté un ID enter seqüencial fresc. Cada sistema extern que va emmagatzemar l’ID antic — la lògica d’encaminament del teu receptor, el teu tauler de monitoratge, la teva documentació — ara fa referència a un webhook mort.

Aquest és el contracte subjacent. L’aplicació l’abstrau: el diàleg Edita realitza esborrar+crear de manera transparent i et mostra el nou ID. Però necessites saber que això està passant, perquè el canvi d’ID té conseqüències reals a la baixa en producció.

Un consell pràctic: emmagatzema els IDs de webhook a la configuració del teu receptor com a variables d’entorn, no codificats. D’aquesta manera, un cicle d’esborrar+crear és una actualització de configuració, no un desplegament de codi.

4. La cua pendingOperations: la teva millor eina de depuració, completament no documentada #

Cada webhook retornat per Webhook.GetAll porta una matriu pendingOperations[]. Cada entrada descriu un esdeveniment que està a la cua per ser lliurat o que ha fallat:

{
  "operation": "UPDATE",
  "rowIDs": [19967],
  "status": "NOT_SENT",
  "lastErrorCode": 0,
  "lastErrorMessage": "",
  "sendAttempts": 0
}

Les operacions poden ser ADD, UPDATE, DELETE o SCHEMA. El camp status, lastErrorCode, lastErrorMessage i sendAttempts et diuen exactament què va intentar FileMaker, quan va fallar i quantes vegades ha reintentat.

Aquesta és la superfície de depuració més útil de tota l’API. També no està enlloc a la documentació pública. La descobreixes llegint una resposta d’API crua.

Quan el Panell d’Operacions Pendents surti, l’aplicació el mostrarà en línia per a cada webhook. Fins llavors, pots inspeccionar la cua llegint la resposta crua Webhook.GetAll — si un webhook està fallant silenciosament, aquest és on primer mires.

5. L’esquema de càrrega útil del receptor no està documentat — l’has d’enginyeria inversa #

Què realment POST FileMaker al teu URL de webhook quan canvia un registre?

No hi ha cap esquema documentat. Ho sabs configurant un endpoint de receptor, registrant el que arribi i fent enginyeria inversa de l’estructura.

Segons les meves proves, una càrrega útil de canvi de contingut es veu així:

{
  "@odata.context": "fmi/odata/v4/Contacts/$metadata#contact(\"uuid\",\"mod_id\",\"row_id\")",
  "value": [
    {
      "@odata.editLink": "fmi/odata/v4/Contacts/contact(3276,...)",
      "@odata.id": "fmi/odata/v4/Contacts/contact(3276,...)",
      "mod_id": 0,
      "row_id": 19071,
      "uuid": "211EE2A8-D2C4-4F14-AA4A-A4B05E60C8FE"
    }
  ]
}

Una notificació de canvi d’esquema es veu completament diferent:

{
  "@odata.context": "fmi/odata/v4/Contacts/$metadata#FileMaker_Tables(...)",
  "value": [
    {
      "BaseTableName": "contact",
      "ModCount": 32,
      "TableId": 1065106,
      "TableName": "contact"
    }
  ]
}

Dues observacions importants:

  • El mod_id és 0 als webhooks invocats manualment (Webhook.Invoke). No van canviar dades realment, així que no hi ha cap ID de modificació a informar. El teu receptor necessita gestionar aquest cas.
  • La càrrega útil només conté els camps llistats a $select. Si vols el contingut del registre, has d’incloure aquests camps a $select en el moment de la creació del webhook, o usar els rowIDs de la càrrega útil per obtenir el registre complet a través d’un OData GET separat.

Les càrregues útils de mostra verificades estan documentades a DISCOVERINGS.md al repositori.

6. Certificats autosignats, CORS i el proxy nginx que no havies pressupostat #

FileMaker Server parla HTTPS usant un certificat autosignat per defecte, i no emet capçaleres CORS. Aquesta combinació significa que una aplicació basada en navegador no pot parlar-li directament en producció — el navegador rebutjarà la sol·licitud abans que mateix surti de la màquina.

L’arquitectura que funciona:

Browser → nginx (your web server)
           ├── /fmwebhooks/*  → serves the React app (dist/)
           └── /fmi/*         → proxy_pass to FileMaker Server
                                 (proxy_ssl_verify off)

nginx finalitza TLS per al teu domini públic, i fa proxy de /fmi/* a FileMaker Server amb proxy_ssl_verify off per acceptar el certificat autosignat de FMS. El frontend utilitza URLs relatives (/fmi/odata/v4/...) al llarg, així que el mateix codi client funciona en desenvolupament (proxy Vite) i producció (proxy nginx) sense modificació.

El repositori inclou una configuració de lloc nginx llesta per usar a docs/servers_enabled/fmwebhooks.conf i un fragment de proxy invers independent a nginx-reverse-proxy.conf.

Aquesta és una decisió d’arquitectura que hauràs de prendre. Els documents mai t’alerten.

7. La bona sorpresa: els webhooks sobreviuen als reinicis del servidor #

Aquí està l’únic que va anar bé.

FileMaker Server persisteix les configuracions de webhook internament. Si reinicies FMS — manteniment planificat, reinici inesperat, cicle d’actualització — els teus webhooks tornen. Webhook.GetAll els retorna exactament com configurats.

Això no està documentat enlloc. Ho vaig confirmar a través de proves deliberades. Per als desplegaments de producció, significa que no necessites tornar a registrar webhooks després de cada esdeveniment del servidor. Les configuracions són duradores.

El biaix, per una vegada, és al teu favor.


Una lectura honesta sobre l’estat actual #

Això sembla una característica que va enviar completa en capacitats i incompleta en documentació.

El motor funciona. El contracte OData és internament consistent un cop el fàs enginyeria inversa. La superfície 22.0.4 — expressions de filtre, notifySchemaChanges, Invoke manual, la cua pendingOperations — està realment ben dissenyada. Algú a Claris va pensar acuradament en aquestes característiques.

Però l’experiència del desenvolupador al voltant és: llegeix l’especificació, construeix una sandbox, mira el que torna, escriu els teus propis documents. Prova, error i una pestanya de xarxa saludable.

Vaig convertir aquesta experiència en una eina de codi obert perquè no hagis de repetir-la.


El que m’agradaria veure a 22.0.5 o 23.0 #

Una llista de desitjos curta per a Claris, en ordre de prioritat:

  • Un esquema de càrrega útil del receptor documentat. Publica simplement el que FMS envia per a cada tipus d’operació. Una pàgina. Estalviaria diverses hores a cada desenvolupador que toqui aquesta API.
  • Un Webhook.Update(<id>) natiu de manera que les edicions no trenquin les referències d’ID externes.
  • IDs de webhooks estables a través de les edicions, o com a mínim un camp de clau estable proporcionat per l’usuari.
  • Signatura HMAC dels webhooks sortints de manera que els receptors puguin verificar la procedència.
  • Una política de reintent documentada i una història maxFailedAttempts visible de punta a punta.
  • Enumeració de scripts via $metadata — avui no hi ha cap manera documentada de llistar els scripts que un compte OData pot cridar.
  • Semàntica lastErrorCode significativa — l’enter opac actual necessita una clau publicada.

Cap d’això és treball d’arquitectura fonamental. És polit d’experiència del desenvolupador que converteix una capacitat poderosa en alguna cosa que la gent desplega sense llegir dos-cents fils de fòrum primer.


El TL;DR #

Les set coses a recordar:

  • Els endpoints de lectura són GET, els endpoints d’acció són POST. El <id> va al camí URL.
  • Mai posis id sense cometes a $select — congela el webhook.
  • Cada edició és un esborrar + crear; els IDs canvien.
  • La cua pendingOperations és el teu depurador.
  • L’esquema de càrrega útil del receptor no està documentat — registra primer, després analitza.
  • La producció necessita un proxy invers nginx per /fmi/*.
  • Els webhooks sobreviuen als reinicis del servidor.

Gestor de webhooks de codi obert: github.com/fsans/FMS-odata-webhooks. Fes-li una estrella si estalvia un cap de setmana.

Si has trobat el teu propi comportament OData de FileMaker no documentat, deixa’l als comentaris. La llista col·lectiva d’errors és, cada cop més, la documentació.


Aquesta és la Part 2 d’una sèrie sobre webhooks OData de FileMaker Server. La Part 1 tracta l’anunci de la característica i el que significa per a la posició de FileMaker en arquitectures modernes.


Lectura addicional: