Documentation

Référence

Les façades — l'API des modules

Mis à jour le 4 septembre 2026Plateforme v1 Markdown brut

Le principe

Une façade = une opération nommée module.entité.op avec un contrat
d’entrée et de sortie fixé par la plateforme. Il n’y a pas de requête
libre
: ce que le registre expose, rien d’autre. Chaque façade exige un
scope feuille et passe par les services de Capibara
sous l’acteur (la personne qui interagit, ou le compte de service de votre
app) — droits, journal, notifications et événements sont ceux d’un humain.

Depuis le code hébergé — ctx.capibara

import { defineApp, ui } from '@capibara-dev/sdk';

export default defineApp({
  pages: {
    home: async ({ ctx }) => {
      const { items } = await ctx.capibara.crm.contacts.list({ q: 'dupont', take: 10 });
      return ui.list({ items: items.map((c) => ({ title: c.displayName, subtitle: c.email ?? '' })) });
    },
  },
  actions: {
    'quote.create': async ({ ctx, form }) => {
      const doc = await ctx.capibara.billing.documents.createDraft({
        type: 'QUOTE',
        partyId: String(form?.partyId),
        lines: [{ description: 'Prestation', quantity: 1, unitPriceCents: 45000 }],
      });
      return { toast: { tone: 'success', text: `Brouillon ${doc.id} créé` }, navigate: `/facturation/documents/${doc.id}` };
    },
  },
});

ctx.capibara est typé par le SDK (AppApi). Un scope manquant renvoie une
erreur scope_not_granted qui nomme le scope à ajouter.

Depuis votre backend — REST

POST /api/public/v1/crm/contacts/list
Authorization: Bearer ck_live_…            (clé API ou access token OAuth du dev)
X-Capibara-Install: <installId>            (l'installation visée)
Content-Type: application/json

{ "q": "dupont", "take": 10 }
  • installId vous est donné par embed-context
    (jeton d’iframe) ou par le portail ; il désigne l’organisation ET votre app.
    Seul le développeur de l’app peut agir au nom de ses installations.
  • Les façades de lecture s’appellent aussi en GET (l’entrée en query
    string) ; les écritures en POST, avec un en-tête Idempotency-Key
    recommandé (rejouer la même clé ne crée pas deux fois).
  • Réponse : { "ok": true, "result": … } ou
    { "ok": false, "error": "<code>", "message": "…" } (+ issues sur une
    entrée invalide).
  • La clé du dev doit couvrir la famille du module (crm:read…) en plus du
    scope feuille accordé à l’installation.
  • Catalogue lisible par machine : GET /api/public/v1/facades (schémas JSON
    d’entrée et de sortie).
  • Deux quotas se cumulent : 120 requêtes / minute par clé (comme le reste
    de l’API publique) et 120 appels / minute par installation.

Avec le SDK : new CapibaraClient({ token }).install(installId).crm.contacts.list({ q }).

Codes d’erreur

Communs aux deux transports (ctx.capibara lève une exception portant le
code ; REST renvoie { ok: false, error, message }) :

Code HTTP Sens
unknown_facade 404 Le nom n’existe pas dans le registre.
scope_not_granted 403 Scope absent du manifeste ou non accordé par l’organisation (le message nomme le scope).
forbidden 403 L’acteur (personne ou compte de service) n’a pas le droit dans l’organisation.
invalid_input 400 L’entrée ne respecte pas le contrat (issues détaille).
conflict / not_found / precondition_failed / bad_request 409 / 404 / 412 / 400 Règles métier du module (e-mail déjà connu, document émis…) — les codes des services de Capibara, en minuscules.
service_account_missing 412 Compte de service absent (organisation en cours de mise à jour) : réinstallez.
bad_output 502 La réponse du module ne correspond plus au contrat de la façade (à signaler).
internal 500 Erreur interne (journalisée côté plateforme).

Propres au transport REST (avant même d’atteindre la façade) :

Code HTTP Sens
unauthorized 401 Authorization absent ou invalide.
key_scope_missing 403 Votre clé ne couvre pas la famille du module (crm:read…).
missing_install 400 En-tête X-Capibara-Install absent.
install_not_found 404 Installation inconnue, inactive ou en pause.
forbidden 403 L’installation n’est pas celle d’une de vos apps.
no_version 412 Aucune version publiée pour cette installation.
consent_outdated 412 La version demande de nouveaux scopes qu’un administrateur n’a pas encore acceptés.
killed 423 Incident actif sur la version (kill switch).
method_not_allowed 405 Façade d’écriture appelée en GET.
rate_limited 429 Quota de la clé ou de l’installation dépassé (Retry-After: 60).

Pagination

Les listes renvoient items et nextCursor : repassez cursor pour la
page suivante ; take est borné (100 au plus).

Référence (générée depuis le registre)

CRM

crm.contacts.list

Lecture · scope crm.contacts:read

Liste paginée des contacts (recherche nom / e-mail / téléphone, étiquettes, vue contacts ou clients).

Entrée Type Requis
q texte
view contacts · clients · all (défaut "all")
tags liste de texte
cursor texte
take nombre (défaut 40)

Sortie : items (liste de objets), nextCursor (texte), total (nombre).

crm.contacts.get

Lecture · scope crm.contacts:read

Une fiche contact par identifiant.

Entrée Type Requis
id texte oui

Sortie : id (texte), kind (texte), displayName (texte), firstName (texte), lastName (texte), email (texte), phone (texte), jobTitle (texte), website (texte), siret (texte), vatNumber (texte), addressLine1 (texte), addressLine2 (texte), postalCode (texte), city (texte), country (texte), isCustomer (booléen), tags (liste de texte), companyId (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.contacts.create

Écriture · scope crm.contacts:write

Crée un contact (au moins un nom ou un e-mail ; un e-mail déjà connu = conflit qui nomme la fiche existante).

Entrée Type Requis
firstName texte
lastName texte
email texte
phone texte
jobTitle texte
companyId texte
addressLine1 texte
addressLine2 texte
postalCode texte
city texte
country texte
tags liste de texte
notes texte
isCustomer booléen

Sortie : id (texte), kind (texte), displayName (texte), firstName (texte), lastName (texte), email (texte), phone (texte), jobTitle (texte), website (texte), siret (texte), vatNumber (texte), addressLine1 (texte), addressLine2 (texte), postalCode (texte), city (texte), country (texte), isCustomer (booléen), tags (liste de texte), companyId (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.contacts.update

Écriture · scope crm.contacts:write

Met à jour un contact (seuls les champs fournis changent).

Entrée Type Requis
id texte oui
firstName texte
lastName texte
email texte
phone texte
jobTitle texte
companyId texte
addressLine1 texte
addressLine2 texte
postalCode texte
city texte
country texte
tags liste de texte
notes texte
isCustomer booléen

Sortie : id (texte), kind (texte), displayName (texte), firstName (texte), lastName (texte), email (texte), phone (texte), jobTitle (texte), website (texte), siret (texte), vatNumber (texte), addressLine1 (texte), addressLine2 (texte), postalCode (texte), city (texte), country (texte), isCustomer (booléen), tags (liste de texte), companyId (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.companies.list

Lecture · scope crm.companies:read

Liste paginée des sociétés.

Entrée Type Requis
q texte
view contacts · clients · all (défaut "all")
tags liste de texte
cursor texte
take nombre (défaut 40)

Sortie : items (liste de objets), nextCursor (texte), total (nombre).

crm.companies.get

Lecture · scope crm.companies:read

Une fiche société par identifiant.

Entrée Type Requis
id texte oui

Sortie : id (texte), kind (texte), displayName (texte), firstName (texte), lastName (texte), email (texte), phone (texte), jobTitle (texte), website (texte), siret (texte), vatNumber (texte), addressLine1 (texte), addressLine2 (texte), postalCode (texte), city (texte), country (texte), isCustomer (booléen), tags (liste de texte), companyId (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.companies.create

Écriture · scope crm.companies:write

Crée une société.

Entrée Type Requis
name texte oui
email texte
phone texte
website texte
siret texte
vatNumber texte
addressLine1 texte
addressLine2 texte
postalCode texte
city texte
country texte
tags liste de texte
notes texte
isCustomer booléen

Sortie : id (texte), kind (texte), displayName (texte), firstName (texte), lastName (texte), email (texte), phone (texte), jobTitle (texte), website (texte), siret (texte), vatNumber (texte), addressLine1 (texte), addressLine2 (texte), postalCode (texte), city (texte), country (texte), isCustomer (booléen), tags (liste de texte), companyId (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.companies.update

Écriture · scope crm.companies:write

Met à jour une société (seuls les champs fournis changent).

Entrée Type Requis
id texte oui
name texte
email texte
phone texte
website texte
siret texte
vatNumber texte
addressLine1 texte
addressLine2 texte
postalCode texte
city texte
country texte
tags liste de texte
notes texte
isCustomer booléen

Sortie : id (texte), kind (texte), displayName (texte), firstName (texte), lastName (texte), email (texte), phone (texte), jobTitle (texte), website (texte), siret (texte), vatNumber (texte), addressLine1 (texte), addressLine2 (texte), postalCode (texte), city (texte), country (texte), isCustomer (booléen), tags (liste de texte), companyId (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.opportunities.list

Lecture · scope crm.opportunities:read

Les opportunités visibles par l’acteur (≤ 1000, les plus récentes d’abord).

Entrée Type Requis
stage NEW · QUALIFIED · PROPOSAL · NEGOTIATION · WON · LOST

Sortie : items (liste de objets).

crm.opportunities.create

Écriture · scope crm.opportunities:write

Crée une opportunité (référence OPP attribuée par la plateforme).

Entrée Type Requis
title texte oui
partyId texte
contactPartyId texte
amountCents nombre (défaut 0)
currency texte (défaut "EUR")
stage NEW · QUALIFIED · PROPOSAL · NEGOTIATION · WON · LOST (défaut "NEW")
probability nombre (défaut 50)
source texte
closeDate date (ISO 8601)
notes texte

Sortie : id (texte), reference (texte), title (texte), partyId (texte), contactPartyId (texte), ownerId (texte), amountCents (nombre), currency (texte), stage (texte), probability (nombre), source (texte), closeDate (date (ISO 8601) ou null), lostReason (texte), notes (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.opportunities.moveStage

Écriture · scope crm.opportunities:write

Fait avancer (ou perdre, avec motif) une opportunité.

Entrée Type Requis
id texte oui
stage NEW · QUALIFIED · PROPOSAL · NEGOTIATION · WON · LOST oui
lostReason texte

Sortie : id (texte), reference (texte), title (texte), partyId (texte), contactPartyId (texte), ownerId (texte), amountCents (nombre), currency (texte), stage (texte), probability (nombre), source (texte), closeDate (date (ISO 8601) ou null), lostReason (texte), notes (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

crm.activities.list

Lecture · scope crm.activities:read

Historique et tâches d’un contact ou d’une opportunité (≤ 200, récentes d’abord).

Entrée Type Requis
partyId texte
opportunityId texte

Sortie : items (liste de objets).

crm.activities.create

Écriture · scope crm.activities:write

Ajoute une note, un appel, un e-mail, un rendez-vous ou une tâche (rattaché à un contact ou une opportunité).

Entrée Type Requis
type CALL · MEETING · EMAIL · NOTE · TASK (défaut "NOTE")
subject texte oui
notes texte
partyId texte
opportunityId texte
scheduledAt date (ISO 8601)
dueAt date (ISO 8601)

Sortie : id (texte), type (texte), subject (texte), notes (texte), scheduledAt (date (ISO 8601) ou null), dueAt (date (ISO 8601) ou null), completedAt (date (ISO 8601) ou null), partyId (texte), opportunityId (texte), assigneeId (texte), createdAt (date (ISO 8601)).

Facturation

billing.documents.list

Lecture · scope billing-fr.documents:read

Liste paginée des devis, factures et avoirs (statut effectif, nom du client, totaux).

Entrée Type Requis
type QUOTE · INVOICE · CREDIT_NOTE · DEPOSIT_INVOICE
status texte
q texte
cursor texte
take nombre (défaut 30)

Sortie : items (liste de objets), nextCursor (texte).

billing.documents.get

Lecture · scope billing-fr.documents:read

Un document avec ses lignes, ses totaux et les avoirs qui le couvrent.

Entrée Type Requis
id texte oui

Sortie : id (texte), type (texte), status (texte), number (texte), currency (texte), finalizedAt (date (ISO 8601) ou null), issuedAt (date (ISO 8601) ou null), sentAt (date (ISO 8601) ou null), dueDate (date (ISO 8601) ou null), paidAt (date (ISO 8601) ou null), validUntil (date (ISO 8601) ou null), acceptedAt (date (ISO 8601) ou null), totalHtCents (nombre), totalTvaCents (nombre), totalTtcCents (nombre), discountBps (nombre), notes (texte), partyId (texte), buyerName (texte), relatedDocumentId (texte), opportunityId (texte), projectId (texte), creditedCents (nombre), lines (liste de objets), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

billing.documents.createDraft

Écriture · scope billing-fr.documents:write

Crée un BROUILLON de devis ou de facture (client par fiche CRM ou saisi) — jamais émis d’office.

Entrée Type Requis
type QUOTE · INVOICE oui
partyId texte
buyer objet
lines liste de objets oui
notes texte
dueDate date (ISO 8601)
validUntil date (ISO 8601)
discountBps nombre (défaut 0)
opportunityId texte
projectId texte

Sortie : id (texte), type (texte), status (texte), number (texte), currency (texte), finalizedAt (date (ISO 8601) ou null), issuedAt (date (ISO 8601) ou null), sentAt (date (ISO 8601) ou null), dueDate (date (ISO 8601) ou null), paidAt (date (ISO 8601) ou null), validUntil (date (ISO 8601) ou null), acceptedAt (date (ISO 8601) ou null), totalHtCents (nombre), totalTvaCents (nombre), totalTtcCents (nombre), discountBps (nombre), notes (texte), partyId (texte), buyerName (texte), relatedDocumentId (texte), opportunityId (texte), projectId (texte), creditedCents (nombre), lines (liste de objets), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

billing.documents.finalize

Écriture · scope billing-fr.documents:write

Émet un brouillon (numéro attribué, archive PDF + Factur-X) ; e-mail au client si une adresse est connue.

Entrée Type Requis
id texte oui
sendEmail booléen (défaut true)

Sortie : id (texte), type (texte), status (texte), number (texte), currency (texte), finalizedAt (date (ISO 8601) ou null), issuedAt (date (ISO 8601) ou null), sentAt (date (ISO 8601) ou null), dueDate (date (ISO 8601) ou null), paidAt (date (ISO 8601) ou null), validUntil (date (ISO 8601) ou null), acceptedAt (date (ISO 8601) ou null), totalHtCents (nombre), totalTvaCents (nombre), totalTtcCents (nombre), discountBps (nombre), notes (texte), partyId (texte), buyerName (texte), relatedDocumentId (texte), opportunityId (texte), projectId (texte), creditedCents (nombre), lines (liste de objets), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

billing.documents.send

Écriture · scope billing-fr.documents:write

Envoie un document ÉMIS au client par e-mail (adresse de la fiche, ou fournie).

Entrée Type Requis
id texte oui
email texte

Sortie : ok (booléen), toEmail (texte).

billing.documents.payLink

Écriture · scope billing-fr.documents:write

Lien de paiement en ligne d’une facture ÉMISE (ou d’une échéance) sur la page de paiement de l’organisation ; returnUrl (domaine déclaré dans returnHosts) ajoute un bouton de retour vers votre site après règlement.

Entrée Type Requis
id texte oui
installmentId texte
returnUrl texte

Sortie : url (texte), path (texte).

billing.charges.create

Écriture · scope billing-fr.pos:write

Crée un encaissement par carte (montant TTC + libellé) que le client règle sur la page de paiement de l’organisation — même rail que le TPE virtuel, valable 5 à 15 min ; returnUrl = bouton de retour vers votre site après règlement.

Entrée Type Requis
amountCents nombre oui
label texte
ttlMinutes nombre
returnUrl texte

Sortie : id (texte), code (texte), formattedCode (texte), amountCents (nombre), currency (texte), expiresAt (date (ISO 8601)), url (texte).

billing.charges.get

Lecture · scope billing-fr.pos:read

État d’un encaissement par carte (en attente, payé, expiré, annulé) — à interroger après le retour du client, ou écouter l’événement pos.charge.paid.

Entrée Type Requis
id texte oui

Sortie : id (texte), status (texte), amountCents (nombre), currency (texte), paidAt (date (ISO 8601) ou null), expiresAt (date (ISO 8601)).

Boutique

shop.products.list

Lecture · scope shop.products:read

Catalogue paginé (60 par page) avec le stock VENDABLE fusionné de chaque produit.

Entrée Type Requis
q texte
status all · published · draft (défaut "all")
cursor texte

Sortie : items (liste de objets), nextCursor (texte).

shop.products.get

Lecture · scope shop.products:read

Un produit avec ses déclinaisons et ses images.

Entrée Type Requis
id texte oui

Sortie : id (texte), sku (texte), name (texte), slug (texte), description (texte), priceCents (nombre), vatRateBps (nombre), currency (texte), isPublished (booléen), isVirtual (booléen), ean (texte), categoryId (texte), brandId (texte), variants (liste de objets), images (liste de objets), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

shop.products.update

Écriture · scope shop.products:write

Modifie un produit : nom, description, prix HT, TVA, publication (jamais le stock — il vit dans les mouvements).

Entrée Type Requis
id texte oui
name texte
description texte
priceCents nombre
vatRateBps nombre
isPublished booléen

Sortie : id (texte), sku (texte), name (texte), slug (texte), priceCents (nombre), vatRateBps (nombre), currency (texte), isPublished (booléen), isVirtual (booléen), ean (texte), categoryId (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

shop.orders.list

Lecture · scope shop.orders:read

Les commandes (récentes d’abord), filtrables par statut.

Entrée Type Requis
status PENDING · PAID · SHIPPED · DELIVERED · CANCELED · REFUNDED
take nombre (défaut 50)

Sortie : items (liste de objets).

shop.orders.get

Lecture · scope shop.orders:read

Une commande avec ses lignes.

Entrée Type Requis
id texte oui

Sortie : id (texte), number (texte), status (texte), channel (texte), currency (texte), customerEmail (texte), customerName (texte), customerPartyId (texte), totalCents (nombre), totalHtCents (nombre), totalVatCents (nombre), shippingCents (nombre), discountCents (nombre), paidAmountCents (nombre), paidAt (date (ISO 8601) ou null), trackingNumber (texte), trackingCarrier (texte), items (liste de objets), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

shop.orders.setStatus

Écriture · scope shop.orders:write

Passe une commande en expédiée ou livrée (le client est prévenu à l’expédition). Jamais payée/remboursée : ce sont des flux d’argent.

Entrée Type Requis
id texte oui
status SHIPPED · DELIVERED oui

Sortie : id (texte), number (texte), status (texte), channel (texte), currency (texte), customerEmail (texte), customerName (texte), customerPartyId (texte), totalCents (nombre), totalHtCents (nombre), totalVatCents (nombre), shippingCents (nombre), discountCents (nombre), paidAmountCents (nombre), paidAt (date (ISO 8601) ou null), trackingNumber (texte), trackingCarrier (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

shop.orders.setTracking

Écriture · scope shop.orders:write

Pose le numéro et le transporteur d’une expédition (repris dans l’e-mail « expédiée »).

Entrée Type Requis
id texte oui
trackingNumber texte ou null oui
trackingCarrier texte ou null

Sortie : id (texte), number (texte), status (texte), channel (texte), currency (texte), customerEmail (texte), customerName (texte), customerPartyId (texte), totalCents (nombre), totalHtCents (nombre), totalVatCents (nombre), shippingCents (nombre), discountCents (nombre), paidAmountCents (nombre), paidAt (date (ISO 8601) ou null), trackingNumber (texte), trackingCarrier (texte), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)).

Projets

projects.list

Lecture · scope projects:read

Les projets (≤ 300, récents d’abord) avec leur avancement.

Entrée Type Requis
status OPEN · ALL · ACTIVE · ON_HOLD · DONE · ARCHIVED (défaut "OPEN")
search texte

Sortie : items (liste de objets).

projects.get

Lecture · scope projects:read

Un projet avec ses colonnes et ses tâches.

Entrée Type Requis
id texte oui

Sortie : id (texte), reference (texte), name (texte), status (texte), clientPartyId (texte), ownerId (texte), billingMode (texte), startDate (date (ISO 8601) ou null), endDate (date (ISO 8601) ou null), completedAt (date (ISO 8601) ou null), createdAt (date (ISO 8601)), updatedAt (date (ISO 8601)), stages (liste de objets), tasks (liste de objets).

projects.tasks.create

Écriture · scope projects.tasks:write

Crée une tâche dans un projet (colonne d’entrée par défaut).

Entrée Type Requis
projectId texte oui
title texte oui
stageId texte
description texte
ownerId texte
dueDate texte
estimateMinutes nombre

Sortie : id (texte).

projects.tasks.move

Écriture · scope projects.tasks:write

Déplace une tâche dans une autre colonne (le statut suit la colonne).

Entrée Type Requis
id texte oui
stageId texte oui

Sortie : ok (booléen).

projects.tasks.comment

Écriture · scope projects.tasks:write

Poste un commentaire sur une tâche (fil de la tâche, notifications habituelles).

Entrée Type Requis
taskId texte oui
body texte oui

Sortie : ok (booléen).

projects.time.log

Écriture · scope projects.tasks:write

Enregistre du temps sur une tâche, au nom de l’acteur (compte de service ou personne).

Entrée Type Requis
taskId texte oui
minutes nombre oui
date texte
description texte
billable booléen

Sortie : id (texte).

Planning

planning.resources.list

Lecture · scope planning.resources:read

Les ressources réservables (salles, personnes, matériel) et leur mode de paiement.

Aucune entrée.

Sortie : items (liste de objets).

planning.bookings.list

Lecture · scope planning.bookings:read

Les réservations qui croisent une fenêtre [from, to], filtrables par ressource et statut.

Entrée Type Requis
from date (ISO 8601)
to date (ISO 8601)
resourceId texte
status SCHEDULED · CONFIRMED · CANCELLED · DONE

Sortie : items (liste de objets).

planning.bookings.create

Écriture · scope planning.bookings:write

Crée une réservation (conflit de créneau refusé, confirmation e-mail au client rattaché).

Entrée Type Requis
title texte oui
resourceId texte
clientPartyId texte
startsAt date (ISO 8601) oui
endsAt date (ISO 8601) oui
notes texte

Sortie : id (texte), title (texte), resourceId (texte), clientPartyId (texte), assigneeUserId (texte), startsAt (date (ISO 8601)), endsAt (date (ISO 8601)), status (texte), notes (texte), priceCents (nombre), paymentStatus (texte), createdAt (date (ISO 8601)).

Site

site.members.list

Lecture · scope site.members:read

Les membres du site public (comptes clients), paginés, filtrables par statut et recherche.

Entrée Type Requis
search texte
status ACTIVE · PENDING · BLOCKED
cursor texte
take nombre (défaut 30)

Sortie : items (liste de objets), nextCursor (texte).

Formation

formation.catalogue.list

Lecture · scope formation.catalogue:read

Le catalogue de formations (actives ; archivées sur demande).

Entrée Type Requis
includeArchived booléen (défaut false)

Sortie : items (liste de objets).

formation.sessions.list

Lecture · scope formation.sessions:read

Les sessions inter-entreprises (à venir par défaut) avec places restantes et inscriptions payées.

Entrée Type Requis
productId texte
includePast booléen (défaut false)

Sortie : items (liste de objets).

Les façades — l'API des modules · Capibara for Developers