Aller au contenu

Programme bêta : trois mois de DeMark gratuits, sans carte. Il reste 25 places sur 25, inscription jusqu’au 16 novembre. Rejoindre la bêta

DeMark

Développeurs

Référence de l'API

Utilisez votre arrière-boutique DeMark depuis votre propre site : prenez des rendez-vous, recevez des demandes, vendez et clavardez. Tout est en JSON sur HTTPS.

URL de base
https://demarkstudio.ca/api/v1
OpenAPI
Télécharger openapi.json

Notions de base

Authentification

Créez vos clés dans Paramètres > Développeurs et envoyez-les dans l'en-tête Authorization. Une clé révoquée cesse de fonctionner aussitôt.

  • dmk_live_... Clé secrète : seulement depuis votre serveur. Elle est refusée si un navigateur l'envoie.
  • dmk_pk_... Clé publique : sans danger dans votre HTML. Elle lit les services, les disponibilités, les produits et les événements, et crée des réservations, des demandes, des paniers, des inscriptions et des tours de clavardage, seulement depuis les domaines autorisés.
Authorization: Bearer dmk_live_...

Erreurs

Toutes les erreurs ont le même corps : un code générique (unauthorized, forbidden, not_found, conflict, validation, rate_limited) et un motif dans message. Les erreurs de validation listent les champs.

{
  "error": {
    "code": "validation",
    "message": "invalid_fields",
    "fields": {
      "email": "invalid_email"
    }
  }
}

Pagination

Les listes renvoient data et next_cursor. Renvoyez next_cursor dans ?cursor= pour la page suivante ; limit va de 1 à 100 (25 par défaut). Un next_cursor nul veut dire que vous êtes à la fin.

{
  "data": [
    "..."
  ],
  "next_cursor": "MTAx"
}

Dates et heures

Les heures sont en ISO 8601 avec le décalage du fuseau de l'entreprise. Vous pouvez envoyer toute heure ISO 8601 avec un décalage ou Z ; sans décalage, elle est lue dans le fuseau de l'entreprise.

Limites de débit

600 requêtes par minute par clé. Chaque réponse porte X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset ; au-delà, vous recevez 429 avec Retry-After.

Compte

L'entreprise et la clé que vous utilisez.

GET /api/v1/me

L'entreprise et la clé de la requête

Fonctionne avec une clé publique

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 429 Rate limited

Exemple de réponse (200)

{
  "business": {
    "id": 12,
    "slug": "salon-ana",
    "name": "Salon Ana",
    "languages": [
      "en",
      "fr"
    ],
    "timezone": "America/Moncton",
    "currency": "CAD",
    "booking_url": "https://demarkstudio.ca/salon-ana/book",
    "site_url": "https://www.salonana.ca"
  },
  "key": {
    "name": "Website",
    "prefix": "dmk_pk_ab12c",
    "type": "public",
    "permissions": [
      "reservas",
      "solicitudes"
    ],
    "scopes": [
      "bookings:create",
      "requests:create",
      "services:read"
    ]
  }
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/me" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

Réservations

Services, plages libres et rendez-vous. Une réservation faite ici envoie les mêmes courriels que la page de réservation.

GET /api/v1/services

Lister les services réservables

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
lang requête string | null Non en or fr; without it, Accept-Language.
cursor requête string | null Non
limit requête integer Non Defaults to the maximum: most businesses fit in one page.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 3,
      "name": "Coupe",
      "description": "Lavage, coupe et coiffage.",
      "duration_min": 45,
      "price": "45.00",
      "currency": "CAD",
      "staff": [
        {
          "id": 1,
          "name": "Julie"
        }
      ],
      "image_url": null
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/services" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

GET /api/v1/availability

Heures libres d'un service pour une journée

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
service requête integer Oui Service id.
date requête string Oui Local day, YYYY-MM-DD.
staff requête integer | null Non Staff id; omit for anyone.
location requête string | null Non Location id or slug (GET /locations); omit for the primary location.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "start": "2026-09-21T09:00:00-03:00",
      "end": "2026-09-21T09:45:00-03:00",
      "staff_id": null
    }
  ],
  "timezone": "America/Moncton"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/availability?service=7&date=2026-09-21" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

GET /api/v1/locations

Lister les emplacements de l'entreprise

Fonctionne avec une clé publique

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 2,
      "name": "Downtown",
      "slug": "downtown",
      "address": "12 King St, Moncton NB",
      "phone": "506 555 0100",
      "timezone": "America/Moncton",
      "primary": true
    }
  ]
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/locations" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/bookings

Prendre un rendez-vous

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
service integer Oui Service id.
start string Oui A start from /availability (ISO 8601).
name string Oui
email string Oui
phone string | null Non
staff integer | null Non Staff id; omit for anyone.
location integer | null Non Location id (GET /locations); omit for the primary location.
notes string | null Non
lang string | null Non en or fr; defaults to the business language.
consent boolean | null Non Opt-in to news from the business.
policy_accepted boolean | null Non Required when the service asks for a deposit or card.

Exemple de corps

{
  "service": 7,
  "start": "2026-09-21T09:00:00-03:00",
  "name": "Lea Roy",
  "email": "lea@example.com",
  "phone": "506 555 0100",
  "staff": null,
  "location": null,
  "notes": "First visit",
  "lang": "en",
  "consent": false,
  "policy_accepted": true
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": 1,
  "status": "confirmed",
  "start": "2026-10-09T09:00:00-03:00",
  "end": "2026-10-09T09:45:00-03:00",
  "service": {
    "id": 3,
    "name": "Coupe"
  },
  "staff": {
    "id": 1,
    "name": "Julie"
  },
  "location": {
    "id": 2,
    "name": "Salon Ana",
    "timezone": "America/Moncton"
  },
  "customer": {
    "name": "Marie Tremblay",
    "email": "marie.tremblay@mail.test",
    "phone": "506 555 0123"
  },
  "notes": "First visit",
  "lang": "fr",
  "source": "api",
  "created_at": "2026-10-02T23:24:52-03:00",
  "token": "IfnZPtmgcfpabtYFc_UU4AxdOWc1MHHGjdUU-jrbLAA",
  "manage_url": "https://demarkstudio.ca/citas/IfnZPtmgcfpabtYFc_UU4AxdOWc1MHHGjdUU-jrbLAA",
  "cancel_url": "https://demarkstudio.ca/citas/IfnZPtmgcfpabtYFc_UU4AxdOWc1MHHGjdUU-jrbLAA/cancel",
  "payment_url": null
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/bookings" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"service": 7, "start": "2026-09-21T09:00:00-03:00", "name": "Lea Roy", "email": "lea@example.com", "phone": "506 555 0100", "staff": null, "location": null, "notes": "First visit", "lang": "en", "consent": false, "policy_accepted": true}'

Retour à l'index

GET /api/v1/bookings

Lister les réservations

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
from requête string | null Non Start day or datetime (ISO).
to requête string | null Non End day (exclusive) or datetime (ISO).
status requête string | null Non pending, confirmed, cancelled, completed or no_show.
location requête integer | null Non Only this location's bookings (GET /locations).
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 1,
      "status": "confirmed",
      "start": "2026-10-09T09:00:00-03:00",
      "end": "2026-10-09T09:45:00-03:00",
      "service": {
        "id": 3,
        "name": "Coupe"
      },
      "staff": {
        "id": 1,
        "name": "Julie"
      },
      "location": {
        "id": 2,
        "name": "Salon Ana",
        "timezone": "America/Moncton"
      },
      "customer": {
        "name": "Marie Tremblay",
        "email": "marie.tremblay@mail.test",
        "phone": "506 555 0123"
      },
      "notes": "First visit",
      "lang": "fr",
      "source": "api",
      "created_at": "2026-10-02T23:24:52-03:00"
    }
  ],
  "next_cursor": "MTAx"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/bookings" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

GET /api/v1/bookings/{booking_id}

Lire une réservation

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
booking_id chemin integer Oui
token requête string | null Non Management token. Required with a public key or without a key.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 1,
  "status": "confirmed",
  "start": "2026-10-09T09:00:00-03:00",
  "end": "2026-10-09T09:45:00-03:00",
  "service": {
    "id": 3,
    "name": "Coupe"
  },
  "staff": {
    "id": 1,
    "name": "Julie"
  },
  "location": {
    "id": 2,
    "name": "Salon Ana",
    "timezone": "America/Moncton"
  },
  "customer": {
    "name": "Marie Tremblay",
    "email": "marie.tremblay@mail.test",
    "phone": "506 555 0123"
  },
  "notes": "First visit",
  "lang": "fr",
  "source": "api",
  "created_at": "2026-10-02T23:24:52-03:00"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/bookings/1" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

DELETE /api/v1/bookings/{booking_id}

Annuler une réservation

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
booking_id chemin integer Oui
token requête string | null Non Management token. Required with a public key or without a key.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 101,
  "status": "cancelled"
}

Essayez avec curl

curl -X DELETE "https://demarkstudio.ca/api/v1/bookings/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

PATCH /api/v1/bookings/{booking_id}

Reprogrammer une réservation ou modifier ses notes

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
booking_id chemin integer Oui

Corps de la requête

NomTypeObligatoireDescription
start string | null Non New start (ISO 8601), from GET /availability/slots. Reschedules the booking: this id is cancelled and a new one is created (see the returned id). Omit to only update notes.
notes string | null Non
location integer | null Non Move the booking to this location (GET /locations). Works like a reschedule: with start, at that time; without it, at the same time. The staff member must work there, the service's room must be one of that location's, and the time must be free there (a staff member's bookings at every location count).

Exemple de corps

{
  "start": "2026-09-21T09:00:00-03:00",
  "notes": "Client asked to move to the morning",
  "location": null
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 101,
  "status": "confirmed",
  "start": "2026-09-21T09:00:00-03:00",
  "end": "2026-09-21T09:45:00-03:00",
  "service": {
    "id": 7,
    "name": "Haircut"
  },
  "staff": {
    "id": 3,
    "name": "Julie"
  },
  "location": {
    "id": 2,
    "name": "Downtown",
    "timezone": "America/Moncton"
  },
  "customer": {
    "name": "Lea Roy",
    "email": "lea@example.com",
    "phone": ""
  },
  "notes": "First visit",
  "lang": "en",
  "source": "api",
  "created_at": "2026-09-14T10:02:11-03:00",
  "manage_url": "https://demarkstudio.ca/citas/kR3...x9"
}

Essayez avec curl

curl -X PATCH "https://demarkstudio.ca/api/v1/bookings/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"start": "2026-09-21T09:00:00-03:00", "notes": "Client asked to move to the morning", "location": null}'

Retour à l'index

GET /api/v1/availability/slots

Heures libres sur une plage de dates

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
service_id requête integer Oui
from requête string Oui First local day, YYYY-MM-DD.
to requête string Oui Last local day, YYYY-MM-DD (inclusive).
staff_id requête integer | null Non
location requête string | null Non Location id or slug (GET /locations); omit for the primary location.

Réponses

  • 200 Successful Response
  • 400 Bad request
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "start": "2026-09-21T09:00:00-03:00",
      "end": "2026-09-21T09:45:00-03:00",
      "staff_id": null
    }
  ],
  "timezone": "America/Moncton"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/availability/slots?service_id=1&from=2026-09-21&to=2026-09-25" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/booking-series

Créer une série de réservations récurrentes

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
service integer Oui Service id.
start string Oui First booking (ISO 8601). Every date keeps this local time.
name string Oui
email string Non
phone string | null Non
staff integer | null Non Staff id; omit to leave it unassigned.
location integer | null Non Location id (GET /locations); omit for the primary location.
notes string | null Non
lang string | null Non en or fr; defaults to the business language.
notify boolean Non Email the customer one message with every date.
recurrence Recurrencia Oui

Exemple de corps

{
  "service": 7,
  "start": "2026-10-06T10:00:00-03:00",
  "name": "Lea Roy",
  "email": "lea@example.com",
  "phone": "506 555 0100",
  "staff": null,
  "location": null,
  "notes": "Physio, every two weeks",
  "lang": "en",
  "notify": true,
  "recurrence": {
    "frequency": "every_2_weeks",
    "count": 6,
    "until": null,
    "skip_conflicts": true
  }
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": 12,
  "frequency": "every_2_weeks",
  "count": 6,
  "until": null,
  "created_at": "2026-10-02T09:12:00-03:00",
  "bookings": [
    {
      "id": 1,
      "status": "confirmed",
      "start": "2026-10-09T09:00:00-03:00",
      "end": "2026-10-09T09:45:00-03:00",
      "service": {
        "id": 3,
        "name": "Coupe"
      },
      "staff": {
        "id": 1,
        "name": "Julie"
      },
      "location": {
        "id": 2,
        "name": "Salon Ana",
        "timezone": "America/Moncton"
      },
      "customer": {
        "name": "Marie Tremblay",
        "email": "marie.tremblay@mail.test",
        "phone": "506 555 0123"
      },
      "notes": "First visit",
      "lang": "fr",
      "source": "api",
      "created_at": "2026-10-02T23:24:52-03:00"
    }
  ],
  "skipped": [
    {
      "start": "2026-10-20T10:00:00-03:00",
      "reasons": [
        "staff_busy"
      ]
    }
  ]
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/booking-series" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"service": 7, "start": "2026-10-06T10:00:00-03:00", "name": "Lea Roy", "email": "lea@example.com", "phone": "506 555 0100", "staff": null, "location": null, "notes": "Physio, every two weeks", "lang": "en", "notify": true, "recurrence": {"frequency": "every_2_weeks", "count": 6, "until": null, "skip_conflicts": true}}'

Retour à l'index

GET /api/v1/booking-series/{series_id}

Lire une série récurrente

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
series_id chemin integer Oui

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 12,
  "frequency": "every_2_weeks",
  "count": 6,
  "until": null,
  "created_at": "2026-10-02T09:12:00-03:00",
  "bookings": [
    {
      "id": 1,
      "status": "confirmed",
      "start": "2026-10-09T09:00:00-03:00",
      "end": "2026-10-09T09:45:00-03:00",
      "service": {
        "id": 3,
        "name": "Coupe"
      },
      "staff": {
        "id": 1,
        "name": "Julie"
      },
      "location": {
        "id": 2,
        "name": "Salon Ana",
        "timezone": "America/Moncton"
      },
      "customer": {
        "name": "Marie Tremblay",
        "email": "marie.tremblay@mail.test",
        "phone": "506 555 0123"
      },
      "notes": "First visit",
      "lang": "fr",
      "source": "api",
      "created_at": "2026-10-02T23:24:52-03:00"
    }
  ],
  "skipped": [
    {
      "start": "2026-10-20T10:00:00-03:00",
      "reasons": [
        "staff_busy"
      ]
    }
  ]
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/booking-series/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/booking-series/{series_id}/cancel

Annuler une série, ou une réservation et les suivantes

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
series_id chemin integer Oui

Corps de la requête

NomTypeObligatoireDescription
from_booking integer | null Non Cancel this booking and the following ones. Omit to cancel every booking of the series that has not started yet.
notify boolean Non Email the customer one message with the cancelled dates.

Exemple de corps

{
  "from_booking": null,
  "notify": true
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 12,
  "cancelled": [
    41,
    42,
    43
  ]
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/booking-series/1/cancel" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"from_booking": null, "notify": true}'

Retour à l'index

Services

Bookable services and their free times.

POST /api/v1/services

Créer un service

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
name_en string Oui
name_fr string Non
description_en string Non
description_fr string Non
duration_min integer Non
price number Non

Exemple de corps

{
  "name_en": "Haircut",
  "name_fr": "Coupe de cheveux",
  "description_en": "Wash, cut and style.",
  "description_fr": "",
  "duration_min": 45,
  "price": 45.0
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": 3,
  "name": "Coupe",
  "description": "Lavage, coupe et coiffage.",
  "duration_min": 45,
  "price": "45.00",
  "currency": "CAD",
  "staff": [
    {
      "id": 1,
      "name": "Julie"
    }
  ],
  "image_url": null
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/services" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name_en": "Haircut", "name_fr": "Coupe de cheveux", "description_en": "Wash, cut and style.", "description_fr": "", "duration_min": 45, "price": 45.0}'

Retour à l'index

GET /api/v1/services/{service_id}

Lire un service

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
service_id chemin integer Oui
lang requête string | null Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 3,
  "name": "Coupe",
  "description": "Lavage, coupe et coiffage.",
  "duration_min": 45,
  "price": "45.00",
  "currency": "CAD",
  "staff": [
    {
      "id": 1,
      "name": "Julie"
    }
  ],
  "image_url": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/services/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

PATCH /api/v1/services/{service_id}

Modifier un service

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
service_id chemin integer Oui

Corps de la requête

NomTypeObligatoireDescription
name_en string | null Non
name_fr string | null Non
duration_min integer | null Non
price number | null Non
active boolean | null Non
staff_ids array[integer] | null Non Replaces the whole list of who can do this service.

Exemple de corps

{
  "name_en": "string",
  "name_fr": "string",
  "duration_min": 1,
  "price": 1.0,
  "active": true,
  "staff_ids": [
    1
  ]
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 3,
  "name": "Coupe",
  "description": "Lavage, coupe et coiffage.",
  "duration_min": 45,
  "price": "45.00",
  "currency": "CAD",
  "staff": [
    {
      "id": 1,
      "name": "Julie"
    }
  ],
  "image_url": null
}

Essayez avec curl

curl -X PATCH "https://demarkstudio.ca/api/v1/services/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name_en": "string", "name_fr": "string", "duration_min": 1, "price": 1.0, "active": true, "staff_ids": [1]}'

Retour à l'index

Demandes

Demandes de soumission, de contact et de soutien. Chacune devient une demande dans l'arrière-boutique, avec ses courriels.

POST /api/v1/requests

Envoyer une demande

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
type string Non quote, contact or support.
name string Oui
email string Oui
phone string | null Non
subject string | null Non
message string Oui
attachment Adjunto | null Non
attachments array[Adjunto] | null Non Up to 3 files (together with attachment).
lang string | null Non
page_url string | null Non

Exemple de corps

{
  "type": "quote",
  "name": "Lea Roy",
  "email": "lea@example.com",
  "phone": "506 555 0100",
  "subject": "Kitchen renovation",
  "message": "We would like a quote for a 12 m2 kitchen.",
  "attachment": {
    "filename": "plan.pdf",
    "content_type": "application/pdf",
    "content_base64": "JVBERi0xLjQK..."
  },
  "attachments": [
    {
      "filename": "plan.pdf",
      "content_type": "application/pdf",
      "content_base64": "JVBERi0xLjQK..."
    }
  ],
  "lang": "en",
  "page_url": "https://www.example.com/contact"
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": 55,
  "status": "new"
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/requests" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"type": "quote", "name": "Lea Roy", "email": "lea@example.com", "phone": "506 555 0100", "subject": "Kitchen renovation", "message": "We would like a quote for a 12 m2 kitchen.", "attachment": {"filename": "plan.pdf", "content_type": "application/pdf", "content_base64": "JVBERi0xLjQK..."}, "attachments": [{"filename": "plan.pdf", "content_type": "application/pdf", "content_base64": "JVBERi0xLjQK..."}], "lang": "en", "page_url": "https://www.example.com/contact"}'

Retour à l'index

GET /api/v1/requests

Lister les demandes

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 1,
      "type": "quote",
      "status": "new",
      "subject": "Wedding party, 6 people",
      "message": "Hair and make-up for six people on a Saturday morning.",
      "customer": {
        "name": "Marc Leblanc",
        "email": "marc.leblanc@mail.test",
        "phone": "506 555 0199"
      },
      "page_url": "https://www.your-salon.ca/weddings",
      "attachments": [
        {
          "id": 1,
          "filename": "inspiration.png",
          "content_type": "image/png",
          "size": 69,
          "url": "https://demarkstudio.ca/adjuntos/2/1?exp=1791253492&sig=c376ff521d8e24efa9fa372d1b46bd445c99acfc839ccd051a54d04c9dff4c3f",
          "expires_at": "2026-10-05T23:24:52-03:00"
        }
      ],
      "lang": "fr",
      "source": "api",
      "created_at": "2026-10-02T23:24:52-03:00"
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/requests" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

Clients

La liste de clients de l'entreprise. Clé secrète seulement.

GET /api/v1/customers

Lister ou chercher des clients

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
email requête string | null Non Exact email.
q requête string | null Non Search in name, email, company, phone.
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 2,
      "name": "Marie Tremblay",
      "email": "marie.tremblay@mail.test",
      "phone": "506 555 0123",
      "company": "",
      "lang": "fr",
      "notes": "Prefers mornings",
      "marketing_consent": false,
      "created_at": "2026-10-02T23:24:52-03:00"
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/customers" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/customers

Ajouter un client

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
name string Oui
email string Oui
phone string | null Non
lang string | null Non
consent boolean Oui Must be true: the customer agreed to be stored.
notes string | null Non

Exemple de corps

{
  "name": "Lea Roy",
  "email": "lea@example.com",
  "phone": "506 555 0100",
  "lang": "fr",
  "consent": true,
  "notes": "Met at the fair"
}

Réponses

  • 200 Already existed
  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 31,
  "name": "Lea Roy",
  "email": "lea@example.com",
  "phone": "506 555 0100",
  "company": "",
  "lang": "fr",
  "notes": "",
  "marketing_consent": false,
  "created_at": "2026-09-14T10:02:11-03:00",
  "created": true
}

Exemple de réponse (201)

{
  "id": 31,
  "name": "Lea Roy",
  "email": "lea@example.com",
  "phone": "506 555 0100",
  "company": "",
  "lang": "fr",
  "notes": "",
  "marketing_consent": false,
  "created_at": "2026-09-14T10:02:11-03:00",
  "created": true
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/customers" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name": "Lea Roy", "email": "lea@example.com", "phone": "506 555 0100", "lang": "fr", "consent": true, "notes": "Met at the fair"}'

Retour à l'index

GET /api/v1/customers/{customer_id}

Lire un client

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
customer_id chemin integer Oui

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 2,
  "name": "Marie Tremblay",
  "email": "marie.tremblay@mail.test",
  "phone": "506 555 0123",
  "company": "",
  "lang": "fr",
  "notes": "Prefers mornings",
  "marketing_consent": false,
  "created_at": "2026-10-02T23:24:52-03:00"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/customers/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

PATCH /api/v1/customers/{customer_id}

Modifier un client

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
customer_id chemin integer Oui

Corps de la requête

NomTypeObligatoireDescription
name string | null Non
email string | null Non 422 if empty; 409 if another customer of this business already has it.
phone string | null Non
lang string | null Non en or fr.
notes string | null Non

Exemple de corps

{
  "name": "string",
  "email": "string",
  "phone": "string",
  "lang": "string",
  "notes": "string"
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 2,
  "name": "Marie Tremblay",
  "email": "marie.tremblay@mail.test",
  "phone": "506 555 0123",
  "company": "",
  "lang": "fr",
  "notes": "Prefers mornings",
  "marketing_consent": false,
  "created_at": "2026-10-02T23:24:52-03:00"
}

Essayez avec curl

curl -X PATCH "https://demarkstudio.ca/api/v1/customers/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name": "string", "email": "string", "phone": "string", "lang": "string", "notes": "string"}'

Retour à l'index

Boutique

Produits, paniers qui mènent au paiement hébergé, et commandes.

GET /api/v1/products

Lister les produits en vente

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
lang requête string | null Non en or fr; without it, Accept-Language.
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 1,
      "name": "Bougie au cedre",
      "description": "",
      "price": "20.00",
      "currency": "CAD",
      "image_url": null,
      "url": "https://demarkstudio.ca/salon-ana/shop/cedar-candle?lang=fr",
      "stock": 10,
      "variants": []
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/products" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/carts

Créer un panier et obtenir son lien de paiement

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
items array[LineaCompra] Oui
lang string | null Non

Exemple de corps

{
  "items": [
    {
      "product": 9,
      "qty": 2,
      "variant": null
    }
  ],
  "lang": "en"
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "checkout_url": "https://demarkstudio.ca/salon-ana/cart?adopt=Qm9..."
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/carts" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"items": [{"product": 9, "qty": 2, "variant": null}], "lang": "en"}'

Retour à l'index

POST /api/v1/orders

Créer une commande

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
items array[LineaCompra] Oui
customer ClientePedido Oui
delivery string | null Non pickup, shipping or digital.
shipping_address string | null Non
notes string | null Non
lang string | null Non

Exemple de corps

{
  "items": [
    {
      "product": 9,
      "qty": 2,
      "variant": null
    }
  ],
  "customer": {
    "name": "Lea Roy",
    "email": "lea@example.com",
    "phone": ""
  },
  "delivery": "pickup",
  "shipping_address": null,
  "notes": null,
  "lang": "en"
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": 18,
  "number": "O-2026-0018",
  "status": "pending_payment",
  "total": "46.00",
  "currency": "CAD",
  "checkout_url": null,
  "order_url": "https://demarkstudio.ca/salon-ana/order/3f1..."
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/orders" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"items": [{"product": 9, "qty": 2, "variant": null}], "customer": {"name": "Lea Roy", "email": "lea@example.com", "phone": ""}, "delivery": "pickup", "shipping_address": null, "notes": null, "lang": "en"}'

Retour à l'index

Products

The shop catalogue: products, options, variants and stock.

POST /api/v1/products

Créer un produit

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
name_en string Oui
name_fr string | null Non
description_en string | null Non
description_fr string | null Non
price_cents integer Oui Base price in cents, in the business currency.
type string Non
stock integer | null Non null = unlimited.
public boolean Non false keeps it as a draft: POST /products/{id}/publish shows it.
option_groups array[OptionGroupInput] Non
variants array[VariantInput] Non Settings for some combinations; the others are calculated.

Exemple de corps

{
  "name_en": "Bird's eye vinyl",
  "name_fr": "Vinyle oeil d'oiseau",
  "description_en": "Wall panel.",
  "description_fr": "Panneau mural.",
  "price_cents": 2000,
  "type": "physical",
  "stock": 10,
  "public": false,
  "option_groups": [
    {
      "id": "colour",
      "name_en": "Colour",
      "name_fr": "Couleur",
      "mode": "surcharge",
      "options": [
        null
      ]
    }
  ],
  "variants": [
    {
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "sku": "BE-HON-12",
      "price_cents": null,
      "stock": 4,
      "active": true
    }
  ]
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": 9,
  "slug": "birds-eye-vinyl",
  "name": "Bird's eye vinyl",
  "name_en": "Bird's eye vinyl",
  "name_fr": "Vinyle oeil d'oiseau",
  "description": "Wall panel.",
  "description_en": "Wall panel.",
  "description_fr": "Panneau mural.",
  "type": "physical",
  "price_cents": 2000,
  "currency": "CAD",
  "stock": 10,
  "public": true,
  "sold_out": false,
  "url": "https://demarkstudio.ca/salon-ana/shop/birds-eye-vinyl",
  "images": [
    {
      "id": 41,
      "url": "https://demarkstudio.ca/m/12/41.webp",
      "thumbnail_url": "https://demarkstudio.ca/m/12/41_t.webp",
      "alt": ""
    }
  ],
  "option_groups": [
    {
      "id": "colour",
      "name": "Colour",
      "name_en": "Colour",
      "name_fr": "Couleur",
      "mode": "surcharge",
      "options": [
        null
      ]
    }
  ],
  "variants": [
    {
      "id": "honey|12x12",
      "sku": "BE-HON-12",
      "price_cents": 1500,
      "stock": 4,
      "shared_stock": false,
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "active": true,
      "available": true
    }
  ],
  "policies": {
    "lang": "en",
    "shipping": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    },
    "returns": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    }
  },
  "created_at": "2026-09-14T10:02:11-03:00",
  "updated_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/products" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name_en": "Bird's eye vinyl", "name_fr": "Vinyle oeil d'oiseau", "description_en": "Wall panel.", "description_fr": "Panneau mural.", "price_cents": 2000, "type": "physical", "stock": 10, "public": false, "option_groups": [{"id": "colour", "name_en": "Colour", "name_fr": "Couleur", "mode": "surcharge", "options": [null]}], "variants": [{"options": {"colour": "honey", "size": "12x12"}, "sku": "BE-HON-12", "price_cents": null, "stock": 4, "active": true}]}'

Retour à l'index

GET /api/v1/products/{product_id}

Lire un produit avec ses options et ses variantes

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
lang requête string | null Non en or fr; without it, Accept-Language.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 9,
  "slug": "birds-eye-vinyl",
  "name": "Bird's eye vinyl",
  "name_en": "Bird's eye vinyl",
  "name_fr": "Vinyle oeil d'oiseau",
  "description": "Wall panel.",
  "description_en": "Wall panel.",
  "description_fr": "Panneau mural.",
  "type": "physical",
  "price_cents": 2000,
  "currency": "CAD",
  "stock": 10,
  "public": true,
  "sold_out": false,
  "url": "https://demarkstudio.ca/salon-ana/shop/birds-eye-vinyl",
  "images": [
    {
      "id": 41,
      "url": "https://demarkstudio.ca/m/12/41.webp",
      "thumbnail_url": "https://demarkstudio.ca/m/12/41_t.webp",
      "alt": ""
    }
  ],
  "option_groups": [
    {
      "id": "colour",
      "name": "Colour",
      "name_en": "Colour",
      "name_fr": "Couleur",
      "mode": "surcharge",
      "options": [
        null
      ]
    }
  ],
  "variants": [
    {
      "id": "honey|12x12",
      "sku": "BE-HON-12",
      "price_cents": 1500,
      "stock": 4,
      "shared_stock": false,
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "active": true,
      "available": true
    }
  ],
  "policies": {
    "lang": "en",
    "shipping": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    },
    "returns": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    }
  },
  "created_at": "2026-09-14T10:02:11-03:00",
  "updated_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/products/1" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

PATCH /api/v1/products/{product_id}

Modifier un produit

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.

Corps de la requête

NomTypeObligatoireDescription
name_en string | null Non
name_fr string | null Non
description_en string | null Non
description_fr string | null Non
price_cents integer | null Non
public boolean | null Non
stock integer | null Non Absolute product stock; null = unlimited. Not together with stock_delta.
stock_delta integer | null Non Refused with 422 insufficient_stock if it would go below 0.

Exemple de corps

{
  "name_en": "Walnut vinyl",
  "name_fr": null,
  "description_en": null,
  "description_fr": null,
  "price_cents": 2200,
  "public": true,
  "stock": null,
  "stock_delta": 5
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 9,
  "slug": "birds-eye-vinyl",
  "name": "Bird's eye vinyl",
  "name_en": "Bird's eye vinyl",
  "name_fr": "Vinyle oeil d'oiseau",
  "description": "Wall panel.",
  "description_en": "Wall panel.",
  "description_fr": "Panneau mural.",
  "type": "physical",
  "price_cents": 2000,
  "currency": "CAD",
  "stock": 10,
  "public": true,
  "sold_out": false,
  "url": "https://demarkstudio.ca/salon-ana/shop/birds-eye-vinyl",
  "images": [
    {
      "id": 41,
      "url": "https://demarkstudio.ca/m/12/41.webp",
      "thumbnail_url": "https://demarkstudio.ca/m/12/41_t.webp",
      "alt": ""
    }
  ],
  "option_groups": [
    {
      "id": "colour",
      "name": "Colour",
      "name_en": "Colour",
      "name_fr": "Couleur",
      "mode": "surcharge",
      "options": [
        null
      ]
    }
  ],
  "variants": [
    {
      "id": "honey|12x12",
      "sku": "BE-HON-12",
      "price_cents": 1500,
      "stock": 4,
      "shared_stock": false,
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "active": true,
      "available": true
    }
  ],
  "policies": {
    "lang": "en",
    "shipping": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    },
    "returns": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    }
  },
  "created_at": "2026-09-14T10:02:11-03:00",
  "updated_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X PATCH "https://demarkstudio.ca/api/v1/products/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name_en": "Walnut vinyl", "name_fr": null, "description_en": null, "description_fr": null, "price_cents": 2200, "public": true, "stock": null, "stock_delta": 5}'

Retour à l'index

POST /api/v1/products/{product_id}/publish

Publier un produit dans la boutique

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 9,
  "slug": "birds-eye-vinyl",
  "name": "Bird's eye vinyl",
  "name_en": "Bird's eye vinyl",
  "name_fr": "Vinyle oeil d'oiseau",
  "description": "Wall panel.",
  "description_en": "Wall panel.",
  "description_fr": "Panneau mural.",
  "type": "physical",
  "price_cents": 2000,
  "currency": "CAD",
  "stock": 10,
  "public": true,
  "sold_out": false,
  "url": "https://demarkstudio.ca/salon-ana/shop/birds-eye-vinyl",
  "images": [
    {
      "id": 41,
      "url": "https://demarkstudio.ca/m/12/41.webp",
      "thumbnail_url": "https://demarkstudio.ca/m/12/41_t.webp",
      "alt": ""
    }
  ],
  "option_groups": [
    {
      "id": "colour",
      "name": "Colour",
      "name_en": "Colour",
      "name_fr": "Couleur",
      "mode": "surcharge",
      "options": [
        null
      ]
    }
  ],
  "variants": [
    {
      "id": "honey|12x12",
      "sku": "BE-HON-12",
      "price_cents": 1500,
      "stock": 4,
      "shared_stock": false,
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "active": true,
      "available": true
    }
  ],
  "policies": {
    "lang": "en",
    "shipping": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    },
    "returns": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    }
  },
  "created_at": "2026-09-14T10:02:11-03:00",
  "updated_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/products/1/publish" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/products/{product_id}/unpublish

Retirer un produit de la boutique

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 9,
  "slug": "birds-eye-vinyl",
  "name": "Bird's eye vinyl",
  "name_en": "Bird's eye vinyl",
  "name_fr": "Vinyle oeil d'oiseau",
  "description": "Wall panel.",
  "description_en": "Wall panel.",
  "description_fr": "Panneau mural.",
  "type": "physical",
  "price_cents": 2000,
  "currency": "CAD",
  "stock": 10,
  "public": true,
  "sold_out": false,
  "url": "https://demarkstudio.ca/salon-ana/shop/birds-eye-vinyl",
  "images": [
    {
      "id": 41,
      "url": "https://demarkstudio.ca/m/12/41.webp",
      "thumbnail_url": "https://demarkstudio.ca/m/12/41_t.webp",
      "alt": ""
    }
  ],
  "option_groups": [
    {
      "id": "colour",
      "name": "Colour",
      "name_en": "Colour",
      "name_fr": "Couleur",
      "mode": "surcharge",
      "options": [
        null
      ]
    }
  ],
  "variants": [
    {
      "id": "honey|12x12",
      "sku": "BE-HON-12",
      "price_cents": 1500,
      "stock": 4,
      "shared_stock": false,
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "active": true,
      "available": true
    }
  ],
  "policies": {
    "lang": "en",
    "shipping": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    },
    "returns": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    }
  },
  "created_at": "2026-09-14T10:02:11-03:00",
  "updated_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/products/1/unpublish" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/products/{product_id}/option-groups

Ajouter un groupe d'options à un produit

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
id string | null Non Group id (slug). Omit it to derive it from name_en.
name_en string Oui
name_fr string | null Non Defaults to name_en.
mode string Non surcharge adds amount_cents; price sets the price. At most one price group per product.
options array[OptionInput] Oui

Exemple de corps

{
  "id": "colour",
  "name_en": "Colour",
  "name_fr": "Couleur",
  "mode": "surcharge",
  "options": [
    {
      "id": "honey",
      "name_en": "Honey maple",
      "name_fr": "Erable miel",
      "amount_cents": 300,
      "image_id": null
    }
  ]
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": "colour",
  "name": "Colour",
  "name_en": "Colour",
  "name_fr": "Couleur",
  "mode": "surcharge",
  "options": [
    {
      "id": "honey",
      "name": "Honey maple",
      "name_en": "Honey maple",
      "name_fr": "Erable miel",
      "amount_cents": null,
      "image_id": null,
      "image_url": null
    }
  ]
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/products/1/option-groups" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"id": "colour", "name_en": "Colour", "name_fr": "Couleur", "mode": "surcharge", "options": [{"id": "honey", "name_en": "Honey maple", "name_fr": "Erable miel", "amount_cents": 300, "image_id": null}]}'

Retour à l'index

PATCH /api/v1/products/{product_id}/option-groups/{group_id}

Modifier un groupe d'options

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
group_id chemin string Oui Option group id.

Corps de la requête

NomTypeObligatoireDescription
name_en string | null Non
name_fr string | null Non
mode string | null Non
options array[OptionInput] | null Non Replaces the whole list. Variants of option ids that disappear are dropped; the others keep sku, price and stock.

Exemple de corps

{
  "name_en": "Finish",
  "name_fr": "Fini",
  "mode": "price",
  "options": [
    {
      "id": "honey",
      "name_en": "Honey maple",
      "name_fr": "Erable miel",
      "amount_cents": 300,
      "image_id": null
    }
  ]
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": "colour",
  "name": "Colour",
  "name_en": "Colour",
  "name_fr": "Couleur",
  "mode": "surcharge",
  "options": [
    {
      "id": "honey",
      "name": "Honey maple",
      "name_en": "Honey maple",
      "name_fr": "Erable miel",
      "amount_cents": null,
      "image_id": null,
      "image_url": null
    }
  ]
}

Essayez avec curl

curl -X PATCH "https://demarkstudio.ca/api/v1/products/1/option-groups/string" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"name_en": "Finish", "name_fr": "Fini", "mode": "price", "options": [{"id": "honey", "name_en": "Honey maple", "name_fr": "Erable miel", "amount_cents": 300, "image_id": null}]}'

Retour à l'index

DELETE /api/v1/products/{product_id}/option-groups/{group_id}

Supprimer un groupe d'options

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
group_id chemin string Oui Option group id.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 9,
  "slug": "birds-eye-vinyl",
  "name": "Bird's eye vinyl",
  "name_en": "Bird's eye vinyl",
  "name_fr": "Vinyle oeil d'oiseau",
  "description": "Wall panel.",
  "description_en": "Wall panel.",
  "description_fr": "Panneau mural.",
  "type": "physical",
  "price_cents": 2000,
  "currency": "CAD",
  "stock": 10,
  "public": true,
  "sold_out": false,
  "url": "https://demarkstudio.ca/salon-ana/shop/birds-eye-vinyl",
  "images": [
    {
      "id": 41,
      "url": "https://demarkstudio.ca/m/12/41.webp",
      "thumbnail_url": "https://demarkstudio.ca/m/12/41_t.webp",
      "alt": ""
    }
  ],
  "option_groups": [
    {
      "id": "colour",
      "name": "Colour",
      "name_en": "Colour",
      "name_fr": "Couleur",
      "mode": "surcharge",
      "options": [
        null
      ]
    }
  ],
  "variants": [
    {
      "id": "honey|12x12",
      "sku": "BE-HON-12",
      "price_cents": 1500,
      "stock": 4,
      "shared_stock": false,
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "active": true,
      "available": true
    }
  ],
  "policies": {
    "lang": "en",
    "shipping": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    },
    "returns": {
      "text": "We ship across New Brunswick for $12.00.",
      "paragraphs": [
        "We ship across New Brunswick for $12.00."
      ],
      "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
    }
  },
  "created_at": "2026-09-14T10:02:11-03:00",
  "updated_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X DELETE "https://demarkstudio.ca/api/v1/products/1/option-groups/string" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/products/{product_id}/variants

Configurer une variante

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
options object Oui One option per group: {group id: option id}.
sku string | null Non
price_cents integer | null Non Fixed price; null = calculated from the product price and the option amounts.
stock integer | null Non Own stock; null = shares the product stock.
active boolean Non An inactive variant is kept but cannot be bought.

Exemple de corps

{
  "options": {
    "colour": "honey",
    "size": "12x12"
  },
  "sku": "BE-HON-12",
  "price_cents": null,
  "stock": 4,
  "active": true
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": "honey|12x12",
  "sku": "BE-HON-12",
  "price_cents": 1500,
  "stock": 4,
  "shared_stock": false,
  "options": {
    "colour": "honey",
    "size": "12x12"
  },
  "active": true,
  "available": true
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/products/1/variants" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"options": {"colour": "honey", "size": "12x12"}, "sku": "BE-HON-12", "price_cents": null, "stock": 4, "active": true}'

Retour à l'index

PATCH /api/v1/products/{product_id}/variants/{variant_id}

Modifier une variante (prix, stock, active)

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
product_id chemin integer Oui Product id.
variant_id chemin string Oui Variant id, '|' URL-encoded as %7C.

Corps de la requête

NomTypeObligatoireDescription
sku string | null Non
price_cents integer | null Non null = calculated.
stock integer | null Non Absolute own stock; null = shares the product stock. Not together with stock_delta.
stock_delta integer | null Non Adds to the stock the variant uses (its own or the shared one). Refused with 422 insufficient_stock if it would go below 0.
active boolean | null Non

Exemple de corps

{
  "sku": "BE-HON-12",
  "price_cents": 2500,
  "stock": null,
  "stock_delta": -2,
  "active": false
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": "honey|12x12",
  "sku": "BE-HON-12",
  "price_cents": 1500,
  "stock": 4,
  "shared_stock": false,
  "options": {
    "colour": "honey",
    "size": "12x12"
  },
  "active": true,
  "available": true
}

Essayez avec curl

curl -X PATCH "https://demarkstudio.ca/api/v1/products/1/variants/string" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"sku": "BE-HON-12", "price_cents": 2500, "stock": null, "stock_delta": -2, "active": false}'

Retour à l'index

GET /api/v1/shop/policies

Lire les politiques de livraison et de retour

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
lang requête string | null Non en or fr.

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "lang": "en",
  "shipping": {
    "text": "We ship across New Brunswick for $12.00.",
    "paragraphs": [
      "We ship across New Brunswick for $12.00."
    ],
    "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
  },
  "returns": {
    "text": "We ship across New Brunswick for $12.00.",
    "paragraphs": [
      "We ship across New Brunswick for $12.00."
    ],
    "url": "https://demarkstudio.ca/salon-ana/shop/shipping"
  }
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/shop/policies" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

Orders

Shop orders and their status.

GET /api/v1/orders

Lister les commandes

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
status requête string | null Non Only orders in this status (pending_payment, paid, preparing, ready, shipped, delivered, cancelled, refunded, paid_after_cancel).
since requête string | null Non Created at or after this ISO date or datetime.
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 18,
      "number": "O-2026-0018",
      "status": "pending_payment",
      "customer": {
        "name": null,
        "email": null,
        "phone": null
      },
      "delivery": "pickup",
      "subtotal": "40.00",
      "shipping": "0.00",
      "tax": "6.00",
      "total": "46.00",
      "currency": "CAD",
      "items": [
        null
      ],
      "created_at": "2026-09-14T10:02:11-03:00",
      "customer_id": 31,
      "subtotal_cents": 4000,
      "shipping_cents": 0,
      "tax_cents": 600,
      "taxes": [
        null
      ],
      "total_cents": 4600,
      "lines": [
        null
      ],
      "allowed_transitions": [
        "paid",
        "cancelled"
      ]
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/orders" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

GET /api/v1/orders/{order_id}

Lire une commande

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
order_id chemin integer Oui

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 18,
  "number": "O-2026-0018",
  "status": "pending_payment",
  "customer": {
    "name": "Lea Roy",
    "email": "lea@example.com",
    "phone": ""
  },
  "delivery": "pickup",
  "subtotal": "40.00",
  "shipping": "0.00",
  "tax": "6.00",
  "total": "46.00",
  "currency": "CAD",
  "items": [
    {
      "product_id": 9,
      "name": "Cedar candle",
      "price": "20.00",
      "qty": 2
    }
  ],
  "created_at": "2026-09-14T10:02:11-03:00",
  "customer_id": 31,
  "subtotal_cents": 4000,
  "shipping_cents": 0,
  "tax_cents": 600,
  "taxes": [
    {
      "name": "GST",
      "rate": 5.0,
      "registration_number": "123456789 RT0001",
      "amount_cents": 300
    }
  ],
  "total_cents": 4600,
  "lines": [
    {
      "product_id": 9,
      "variant_id": "honey|12x12",
      "name": "Bird's eye vinyl",
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "options_label": "Colour: Honey maple, Size: 12 x 12 in",
      "qty": 2,
      "unit_price_cents": 1500,
      "total_cents": 3000
    }
  ],
  "allowed_transitions": [
    "paid",
    "cancelled"
  ],
  "history": [
    {
      "status": "paid",
      "at": "2026-09-14T10:05:00-03:00",
      "source": "system"
    }
  ]
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/orders/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

PATCH /api/v1/orders/{order_id}/status

Changer le statut d'une commande

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
order_id chemin integer Oui

Corps de la requête

NomTypeObligatoireDescription
status string Oui preparing, ready, shipped, delivered, cancelled, refunded, or paid (only with manual_payment).
manual_payment boolean Non Required (true) to mark an order paid: payment taken outside DeMark. Audited.
tracking string | null Non Tracking number for shipped.

Exemple de corps

{
  "status": "shipped",
  "manual_payment": false,
  "tracking": "CA123456789"
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, scope or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 18,
  "number": "O-2026-0018",
  "status": "pending_payment",
  "customer": {
    "name": "Lea Roy",
    "email": "lea@example.com",
    "phone": ""
  },
  "delivery": "pickup",
  "subtotal": "40.00",
  "shipping": "0.00",
  "tax": "6.00",
  "total": "46.00",
  "currency": "CAD",
  "items": [
    {
      "product_id": 9,
      "name": "Cedar candle",
      "price": "20.00",
      "qty": 2
    }
  ],
  "created_at": "2026-09-14T10:02:11-03:00",
  "customer_id": 31,
  "subtotal_cents": 4000,
  "shipping_cents": 0,
  "tax_cents": 600,
  "taxes": [
    {
      "name": "GST",
      "rate": 5.0,
      "registration_number": "123456789 RT0001",
      "amount_cents": 300
    }
  ],
  "total_cents": 4600,
  "lines": [
    {
      "product_id": 9,
      "variant_id": "honey|12x12",
      "name": "Bird's eye vinyl",
      "options": {
        "colour": "honey",
        "size": "12x12"
      },
      "options_label": "Colour: Honey maple, Size: 12 x 12 in",
      "qty": 2,
      "unit_price_cents": 1500,
      "total_cents": 3000
    }
  ],
  "allowed_transitions": [
    "paid",
    "cancelled"
  ],
  "history": [
    {
      "status": "paid",
      "at": "2026-09-14T10:05:00-03:00",
      "source": "system"
    }
  ]
}

Essayez avec curl

curl -X PATCH "https://demarkstudio.ca/api/v1/orders/1/status" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"status": "shipped", "manual_payment": false, "tracking": "CA123456789"}'

Retour à l'index

Quotes

Quotes sent to customers.

GET /api/v1/quotes

Lister les soumissions

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 14,
      "number": "Q-2026-0014",
      "status": "sent",
      "title": "Kitchen renovation",
      "customer": {
        "name": null,
        "email": null,
        "phone": null
      },
      "currency": "CAD",
      "base": "1200.00",
      "tax": "180.00",
      "taxes": [
        null
      ],
      "total": "1380.00",
      "valid_until": "2026-10-15",
      "lines": [
        null
      ],
      "public_url": null,
      "created_at": "2026-09-14T10:02:11-03:00",
      "updated_at": "2026-09-14T10:02:11-03:00"
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/quotes" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

GET /api/v1/quotes/{quote_id}

Lire une soumission

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
quote_id chemin integer Oui

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 14,
  "number": "Q-2026-0014",
  "status": "sent",
  "title": "Kitchen renovation",
  "customer": {
    "name": "Lea Roy",
    "email": "lea@example.com",
    "phone": ""
  },
  "currency": "CAD",
  "base": "1200.00",
  "tax": "180.00",
  "taxes": [
    {
      "name": "GST",
      "rate": 5.0,
      "registration_number": "123456789 RT0001",
      "amount": "60.00"
    }
  ],
  "total": "1380.00",
  "valid_until": "2026-10-15",
  "lines": [
    {
      "concept": "Kitchen cabinets",
      "detail": "",
      "qty": 1.0,
      "unit_price": "1200.00",
      "amount": "1200.00",
      "tax_exempt": false,
      "optional": false
    }
  ],
  "public_url": null,
  "created_at": "2026-09-14T10:02:11-03:00",
  "updated_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/quotes/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

Invoices

Invoices and their payments.

GET /api/v1/invoices

Lister les factures

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 42,
      "number": "2026-0042",
      "status": "issued",
      "customer": {
        "name": null,
        "email": null,
        "phone": null
      },
      "currency": "CAD",
      "base": "1200.00",
      "tax": "180.00",
      "taxes": [
        null
      ],
      "total": "1380.00",
      "due_date": "2026-10-14",
      "paid_at": null,
      "lines": [
        null
      ],
      "payments": [
        null
      ],
      "created_at": "2026-09-14T10:02:11-03:00"
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/invoices" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

GET /api/v1/invoices/{invoice_id}

Lire une facture

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
invoice_id chemin integer Oui

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 42,
  "number": "2026-0042",
  "status": "issued",
  "customer": {
    "name": "Lea Roy",
    "email": "lea@example.com",
    "phone": ""
  },
  "currency": "CAD",
  "base": "1200.00",
  "tax": "180.00",
  "taxes": [
    {
      "name": "GST",
      "rate": 5.0,
      "registration_number": "123456789 RT0001",
      "amount": "60.00"
    }
  ],
  "total": "1380.00",
  "due_date": "2026-10-14",
  "paid_at": null,
  "lines": [
    {
      "concept": "Kitchen cabinets",
      "detail": "",
      "qty": 1.0,
      "unit_price": "1200.00",
      "amount": "1200.00",
      "tax_exempt": false
    }
  ],
  "payments": [
    {
      "provider": "stripe",
      "amount": "1380.00",
      "currency": "CAD",
      "status": "paid",
      "reference": "pi_3Nk...",
      "created_at": "2026-09-14T10:02:11-03:00"
    }
  ],
  "created_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/invoices/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/invoices/{invoice_id}/mark-paid

Marquer une facture comme payée

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
invoice_id chemin integer Oui
Idempotency-Key en-tête string Non Retry safely: the first 2xx response is kept 24 hours and replayed with Idempotent-Replayed: true. Same key with a different body: 422 idempotency_key_reused.

Corps de la requête

NomTypeObligatoireDescription
method string Oui
reference string | null Non
paid_at string | null Non ISO 8601; defaults to now.

Exemple de corps

{
  "method": "e-transfer",
  "reference": "ET-88213",
  "paid_at": null
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 409 Conflict
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 42,
  "number": "2026-0042",
  "status": "issued",
  "customer": {
    "name": "Lea Roy",
    "email": "lea@example.com",
    "phone": ""
  },
  "currency": "CAD",
  "base": "1200.00",
  "tax": "180.00",
  "taxes": [
    {
      "name": "GST",
      "rate": 5.0,
      "registration_number": "123456789 RT0001",
      "amount": "60.00"
    }
  ],
  "total": "1380.00",
  "due_date": "2026-10-14",
  "paid_at": null,
  "lines": [
    {
      "concept": "Kitchen cabinets",
      "detail": "",
      "qty": 1.0,
      "unit_price": "1200.00",
      "amount": "1200.00",
      "tax_exempt": false
    }
  ],
  "payments": [
    {
      "provider": "stripe",
      "amount": "1380.00",
      "currency": "CAD",
      "status": "paid",
      "reference": "pi_3Nk...",
      "created_at": "2026-09-14T10:02:11-03:00"
    }
  ],
  "created_at": "2026-09-14T10:02:11-03:00"
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/invoices/1/mark-paid" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"method": "e-transfer", "reference": "ET-88213", "paid_at": null}'

Retour à l'index

Projects

Project portfolio entries with their photos.

GET /api/v1/works

Lister les réalisations

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
lang requête string | null Non
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": 3,
      "slug": "kitchen-in-maple",
      "url": "https://demarkstudio.ca/salon-ana/work/kitchen-in-maple",
      "title": "Kitchen in maple",
      "summary": "A full kitchen remodel in solid maple.",
      "detail": [
        "We replaced the cabinets..."
      ],
      "materials": "Solid maple, quartz counters",
      "measurements": "12 m2",
      "location": "Moncton, NB",
      "delivered": "March 2026",
      "delivered_iso": "2026-03",
      "duration": "3 weeks",
      "published": true,
      "cover": null,
      "photos": [
        null
      ]
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/works" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

GET /api/v1/works/{work_id}

Lire une réalisation

Clé secrète seulement

Paramètres

NomDansTypeObligatoireDescription
work_id chemin integer Oui
lang requête string | null Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "id": 3,
  "slug": "kitchen-in-maple",
  "url": "https://demarkstudio.ca/salon-ana/work/kitchen-in-maple",
  "title": "Kitchen in maple",
  "summary": "A full kitchen remodel in solid maple.",
  "detail": [
    "We replaced the cabinets..."
  ],
  "materials": "Solid maple, quartz counters",
  "measurements": "12 m2",
  "location": "Moncton, NB",
  "delivered": "March 2026",
  "delivered_iso": "2026-03",
  "duration": "3 weeks",
  "published": true,
  "cover": {
    "id": 9,
    "url": "https://demarkstudio.ca/m/12/40.webp",
    "caption": "Before",
    "alt": "Kitchen before the renovation",
    "width": 1600,
    "height": 1200
  },
  "photos": [
    {
      "id": 9,
      "url": "https://demarkstudio.ca/m/12/40.webp",
      "caption": "Before",
      "alt": "Kitchen before the renovation",
      "width": 1600,
      "height": 1200
    }
  ]
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/works/1" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

Événements

Prochaines dates d'événements et inscriptions.

GET /api/v1/events

Lister les prochaines dates d'événements

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
from requête string | null Non First day, YYYY-MM-DD (today by default).
lang requête string | null Non en or fr; without it, Accept-Language.
cursor requête string | null Non
limit requête integer Non

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "id": "1-2026-10-14",
      "event_id": 1,
      "title": "Atelier de soins capillaires",
      "description": "Deux heures pour apprendre une routine qui dure.",
      "start": "2026-10-14T18:00:00-03:00",
      "end": "2026-10-14T20:00:00-03:00",
      "seats_left": 12,
      "price": "25.00",
      "currency": "CAD",
      "url": "https://demarkstudio.ca/salon-ana/events/hair-care-workshop?ocurrencia=2026-10-14&lang=fr"
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/events" \
  -H "Authorization: Bearer dmk_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

POST /api/v1/events/{event_id}/registrations

S'inscrire à une date d'événement

Fonctionne avec une clé publique

Paramètres

NomDansTypeObligatoireDescription
event_id chemin string Oui

Corps de la requête

NomTypeObligatoireDescription
occurrence string Oui Occurrence id from /events, or its date YYYY-MM-DD.
name string Oui
email string Oui
phone string | null Non
seats integer Non
lang string | null Non

Exemple de corps

{
  "occurrence": "4-2026-09-20",
  "name": "Lea Roy",
  "email": "lea@example.com",
  "phone": null,
  "seats": 2,
  "lang": "en"
}

Réponses

  • 201 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (201)

{
  "id": 77,
  "status": "confirmed"
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/events/string/registrations" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"occurrence": "4-2026-09-20", "name": "Lea Roy", "email": "lea@example.com", "phone": null, "seats": 2, "lang": "en"}'

Retour à l'index

Clavardage

Un tour du clavardage de triage, le même que celui du widget.

POST /api/v1/chat

Envoyer un tour de clavardage

Fonctionne avec une clé publique

Corps de la requête

NomTypeObligatoireDescription
session string | null Non Omit on the first turn; send back the one you get.
message string Non
action string | null Non An option id from the previous reply.
fields object | null Non Form values: nombre, email, detalle.
lang string | null Non
page_url string | null Non

Exemple de corps

{
  "session": "s8f7a6d5c4b3a2",
  "message": "Do you open on Sundays?",
  "action": null,
  "fields": null,
  "lang": "en",
  "page_url": "https://www.example.com/"
}

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 404 Not found
  • 422 Validation error
  • 429 Rate limited

Exemple de réponse (200)

{
  "session": "s8f7a6d5c4b3a2",
  "reply": "We are open Sunday from 10 to 4.",
  "options": [
    {
      "id": "reservar",
      "label": "Book an appointment"
    }
  ],
  "form": [
    {
      "name": "email",
      "type": "email",
      "label": "Email",
      "value": ""
    }
  ],
  "state": "saludo",
  "handoff": false
}

Essayez avec curl

curl -X POST "https://demarkstudio.ca/api/v1/chat" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"session": "s8f7a6d5c4b3a2", "message": "Do you open on Sundays?", "action": null, "fields": null, "lang": "en", "page_url": "https://www.example.com/"}'

Retour à l'index

Webhooks

Les événements que DeMark peut envoyer à votre serveur.

GET /api/v1/webhooks/events

Lister les noms d'événements webhook

Clé secrète seulement

Réponses

  • 200 Successful Response
  • 401 Missing, invalid or revoked API key
  • 403 Forbidden: key type, permission, origin or plan
  • 429 Rate limited

Exemple de réponse (200)

{
  "data": [
    {
      "name": "booking.created"
    }
  ],
  "next_cursor": null
}

Essayez avec curl

curl -X GET "https://demarkstudio.ca/api/v1/webhooks/events" \
  -H "Authorization: Bearer dmk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Retour à l'index

Modèles

Les objets que renvoie l'API et qu'envoient les webhooks. Les dates portent le décalage horaire de votre entreprise, les montants sont des chaînes décimales et chaque valeur est la valeur publique en anglais.

Booking

Champs de Booking
NomTypeObligatoireDescription
id integer Oui
status string Oui pending, confirmed, cancelled, completed or no_show.
start string Oui ISO 8601 with the business offset.
end string Oui
service ServiceRef | null Oui null when the service was deleted.
staff StaffRef | null Oui null when anyone can do it.
location LocationRef | null Oui Where it takes place (GET /locations). start and end carry the business offset; the location time zone is here.
customer CustomerRef Oui
notes string | null Oui
lang string | null Oui en or fr: the language of the booking and its emails.
source string | null Oui Where it was made: web, api, panel, portal...
created_at string | null Oui

Exemple réel

{
  "id": 1,
  "status": "confirmed",
  "start": "2026-10-09T09:00:00-03:00",
  "end": "2026-10-09T09:45:00-03:00",
  "service": {
    "id": 3,
    "name": "Coupe"
  },
  "staff": {
    "id": 1,
    "name": "Julie"
  },
  "location": {
    "id": 2,
    "name": "Salon Ana",
    "timezone": "America/Moncton"
  },
  "customer": {
    "name": "Marie Tremblay",
    "email": "marie.tremblay@mail.test",
    "phone": "506 555 0123"
  },
  "notes": "First visit",
  "lang": "fr",
  "source": "api",
  "created_at": "2026-10-02T23:24:52-03:00"
}

NewBooking

Champs de NewBooking
NomTypeObligatoireDescription
id integer Oui
status string Oui pending, confirmed, cancelled, completed or no_show.
start string Oui ISO 8601 with the business offset.
end string Oui
service ServiceRef | null Oui null when the service was deleted.
staff StaffRef | null Oui null when anyone can do it.
location LocationRef | null Oui Where it takes place (GET /locations). start and end carry the business offset; the location time zone is here.
customer CustomerRef Oui
notes string | null Oui
lang string | null Oui en or fr: the language of the booking and its emails.
source string | null Oui Where it was made: web, api, panel, portal...
created_at string | null Oui
token string Oui Management token. Shown once: store it to read or cancel the booking.
manage_url string Oui Page where the visitor manages the booking.
cancel_url string Oui Page where the visitor confirms the cancellation (GET, no key). Servers cancel with DELETE /bookings/{id}?token=... or with a secret key.
payment_url string | null Oui Deposit or card checkout, when the service asks for it.

Exemple réel

{
  "id": 1,
  "status": "confirmed",
  "start": "2026-10-09T09:00:00-03:00",
  "end": "2026-10-09T09:45:00-03:00",
  "service": {
    "id": 3,
    "name": "Coupe"
  },
  "staff": {
    "id": 1,
    "name": "Julie"
  },
  "location": {
    "id": 2,
    "name": "Salon Ana",
    "timezone": "America/Moncton"
  },
  "customer": {
    "name": "Marie Tremblay",
    "email": "marie.tremblay@mail.test",
    "phone": "506 555 0123"
  },
  "notes": "First visit",
  "lang": "fr",
  "source": "api",
  "created_at": "2026-10-02T23:24:52-03:00",
  "token": "IfnZPtmgcfpabtYFc_UU4AxdOWc1MHHGjdUU-jrbLAA",
  "manage_url": "https://demarkstudio.ca/citas/IfnZPtmgcfpabtYFc_UU4AxdOWc1MHHGjdUU-jrbLAA",
  "cancel_url": "https://demarkstudio.ca/citas/IfnZPtmgcfpabtYFc_UU4AxdOWc1MHHGjdUU-jrbLAA/cancel",
  "payment_url": null
}

Request

Champs de Request
NomTypeObligatoireDescription
id integer Oui
type string Oui quote, contact or support (also lead, booking, question, event, table_booking, other for requests that came from other channels).
status string Oui new, open, waiting_customer, resolved or closed.
subject string Oui
message string Oui What the customer wrote, without page or file lines.
customer CustomerRef Oui
page_url string | null Oui Page the request was sent from, when known.
attachments array[Attachment] Oui Empty when there are none.
lang string | null Oui
source string Oui api, web, site, chat, email...
created_at string Oui

Exemple réel

{
  "id": 1,
  "type": "quote",
  "status": "new",
  "subject": "Wedding party, 6 people",
  "message": "Hair and make-up for six people on a Saturday morning.",
  "customer": {
    "name": "Marc Leblanc",
    "email": "marc.leblanc@mail.test",
    "phone": "506 555 0199"
  },
  "page_url": "https://www.your-salon.ca/weddings",
  "attachments": [
    {
      "id": 1,
      "filename": "inspiration.png",
      "content_type": "image/png",
      "size": 69,
      "url": "https://demarkstudio.ca/adjuntos/2/1?exp=1791253492&sig=c376ff521d8e24efa9fa372d1b46bd445c99acfc839ccd051a54d04c9dff4c3f",
      "expires_at": "2026-10-05T23:24:52-03:00"
    }
  ],
  "lang": "fr",
  "source": "api",
  "created_at": "2026-10-02T23:24:52-03:00"
}

Attachment

Champs de Attachment
NomTypeObligatoireDescription
id integer Oui
filename string Oui
content_type string Oui
size integer Oui Bytes.
url string Oui Signed download link; no key needed until expires_at.
expires_at string Oui ISO 8601; ask for the request again to get a fresh url.

Exemple réel

{
  "id": 1,
  "filename": "inspiration.png",
  "content_type": "image/png",
  "size": 69,
  "url": "https://demarkstudio.ca/adjuntos/2/1?exp=1791253492&sig=c376ff521d8e24efa9fa372d1b46bd445c99acfc839ccd051a54d04c9dff4c3f",
  "expires_at": "2026-10-05T23:24:52-03:00"
}

Customer

Champs de Customer
NomTypeObligatoireDescription
id integer Oui
name string Oui
email string Oui
phone string Oui
company string Oui
lang string Oui
notes string Oui
marketing_consent boolean Oui
created_at string | null Oui

Exemple réel

{
  "id": 2,
  "name": "Marie Tremblay",
  "email": "marie.tremblay@mail.test",
  "phone": "506 555 0123",
  "company": "",
  "lang": "fr",
  "notes": "Prefers mornings",
  "marketing_consent": false,
  "created_at": "2026-10-02T23:24:52-03:00"
}

Order

Champs de Order
NomTypeObligatoireDescription
id integer Oui
number string Oui
status string Oui pending_payment, paid, preparing, ready, shipped, delivered, cancelled, refunded or paid_after_cancel.
customer CustomerRef Oui
delivery string Oui pickup, shipping, digital or empty.
subtotal string Oui
shipping string Oui
tax string Oui
total string Oui
currency string Oui
items array[OrderItem] Oui
created_at string Oui

Exemple réel

{
  "id": 1,
  "number": "O-2026-0001",
  "status": "paid",
  "customer": {
    "name": "Lea Roy",
    "email": "lea.roy@mail.test",
    "phone": ""
  },
  "delivery": "pickup",
  "subtotal": "40.00",
  "shipping": "0.00",
  "tax": "0.00",
  "total": "40.00",
  "currency": "CAD",
  "items": [
    {
      "product_id": 1,
      "name": "Cedar candle",
      "price": "20.00",
      "qty": 2
    }
  ],
  "created_at": "2026-10-02T23:24:52-03:00"
}

Event

Champs de Event
NomTypeObligatoireDescription
id string Oui Occurrence id: <event_id>-<YYYY-MM-DD>.
event_id integer Oui
title string Oui In the requested language.
description string Oui
start string Oui
end string Oui
seats_left integer | null Oui null = no capacity limit.
price string | null Oui
currency string Oui
url string Oui Event page in the requested language.

Exemple réel

{
  "id": "1-2026-10-14",
  "event_id": 1,
  "title": "Atelier de soins capillaires",
  "description": "Deux heures pour apprendre une routine qui dure.",
  "start": "2026-10-14T18:00:00-03:00",
  "end": "2026-10-14T20:00:00-03:00",
  "seats_left": 12,
  "price": "25.00",
  "currency": "CAD",
  "url": "https://demarkstudio.ca/salon-ana/events/hair-care-workshop?ocurrencia=2026-10-14&lang=fr"
}

Service

Champs de Service
NomTypeObligatoireDescription
id integer Oui
name string Oui In the requested language.
description string Oui
duration_min integer Oui
price string | null Oui Decimal as string, or null when the service has no price.
currency string Oui
staff array[StaffRef] Oui Who can do it; empty when the business has no team.
image_url string | null Oui

Exemple réel

{
  "id": 3,
  "name": "Coupe",
  "description": "Lavage, coupe et coiffage.",
  "duration_min": 45,
  "price": "45.00",
  "currency": "CAD",
  "staff": [
    {
      "id": 1,
      "name": "Julie"
    }
  ],
  "image_url": null
}

Product

Champs de Product
NomTypeObligatoireDescription
id integer Oui
name string Oui
description string Oui
price string | null Oui
currency string Oui
image_url string | null Oui
url string Oui Product page in the requested language.
stock integer | null Oui null = unlimited.
variants array[object] Oui Active variants (id, sku, price_cents, stock, options, active, available); empty when the product has no options.

Exemple réel

{
  "id": 1,
  "name": "Bougie au cedre",
  "description": "",
  "price": "20.00",
  "currency": "CAD",
  "image_url": null,
  "url": "https://demarkstudio.ca/salon-ana/shop/cedar-candle?lang=fr",
  "stock": 10,
  "variants": []
}

Corps des webhooks

Chaque corps ci-dessous a été généré par DeMark à partir d'une réservation, d'une demande, d'une commande et d'un client de test. data est le même modèle que celui de l'API REST : une seule classe dans votre code lit les deux.

La version 1 ne fait qu'ajouter des champs : ignorez ceux que vous ne connaissez pas. created reste un alias UTC de created_at pour les anciens récepteurs.

POST booking.created

Une réservation est confirmée, qu'elle vienne d'un widget, de l'API, de votre page de réservation ou de l'arrière-boutique. data est un WebhookBooking

{
  "business": {
    "id": 2,
    "slug": "salon-ana"
  },
  "created": "2026-10-03T02:24:52.567Z",
  "created_at": "2026-10-02T23:24:52-03:00",
  "data": {
    "created_at": "2026-10-02T23:24:52-03:00",
    "customer": {
      "email": "marie.tremblay@mail.test",
      "name": "Marie Tremblay",
      "phone": "506 555 0123"
    },
    "end": "2026-10-09T09:45:00-03:00",
    "id": 1,
    "lang": "fr",
    "location": {
      "id": 2,
      "name": "Salon Ana",
      "timezone": "America/Moncton"
    },
    "manage_url": "https://demarkstudio.ca/citas/c2-1-12f82226c4db44f694f2343dd1942d94",
    "notes": "First visit",
    "service": {
      "id": 3,
      "name": "Coupe"
    },
    "source": "api",
    "staff": {
      "id": 1,
      "name": "Julie"
    },
    "start": "2026-10-09T09:00:00-03:00",
    "status": "confirmed"
  },
  "id": "evt_2",
  "type": "booking.created"
}

Retour à l'index

POST booking.cancelled

Une réservation est annulée, par le client ou par vous. data est un WebhookBooking

{
  "business": {
    "id": 2,
    "slug": "salon-ana"
  },
  "created": "2026-10-03T02:24:52.609Z",
  "created_at": "2026-10-02T23:24:52-03:00",
  "data": {
    "created_at": "2026-10-02T23:24:52-03:00",
    "customer": {
      "email": "luc.arsenault@mail.test",
      "name": "Luc Arsenault",
      "phone": ""
    },
    "end": "2026-10-09T10:45:00-03:00",
    "id": 2,
    "lang": "en",
    "location": {
      "id": 2,
      "name": "Salon Ana",
      "timezone": "America/Moncton"
    },
    "manage_url": "https://demarkstudio.ca/citas/c2-2-dcd2cbc1d9ca3db5593cd8364bf6349b",
    "notes": "",
    "service": {
      "id": 3,
      "name": "Haircut"
    },
    "source": "api",
    "staff": {
      "id": 1,
      "name": "Julie"
    },
    "start": "2026-10-09T10:00:00-03:00",
    "status": "cancelled"
  },
  "id": "evt_5",
  "type": "booking.cancelled"
}

Retour à l'index

POST request.created

Une demande de soumission, de contact ou de soutien arrive. data est un Request

{
  "business": {
    "id": 2,
    "slug": "salon-ana"
  },
  "created": "2026-10-03T02:24:52.624Z",
  "created_at": "2026-10-02T23:24:52-03:00",
  "data": {
    "attachments": [
      {
        "content_type": "image/png",
        "expires_at": "2026-10-05T23:24:52-03:00",
        "filename": "inspiration.png",
        "id": 1,
        "size": 69,
        "url": "https://demarkstudio.ca/adjuntos/2/1?exp=1791253492&sig=c376ff521d8e24efa9fa372d1b46bd445c99acfc839ccd051a54d04c9dff4c3f"
      }
    ],
    "created_at": "2026-10-02T23:24:52-03:00",
    "customer": {
      "email": "marc.leblanc@mail.test",
      "name": "Marc Leblanc",
      "phone": "506 555 0199"
    },
    "id": 1,
    "lang": "fr",
    "message": "Hair and make-up for six people on a Saturday morning.",
    "page_url": "https://www.your-salon.ca/weddings",
    "source": "api",
    "status": "new",
    "subject": "Wedding party, 6 people",
    "type": "quote"
  },
  "id": "evt_7",
  "type": "request.created"
}

Retour à l'index

POST order.paid

Une commande est payée. data est un Order

{
  "business": {
    "id": 2,
    "slug": "salon-ana"
  },
  "created": "2026-10-03T02:24:52.652Z",
  "created_at": "2026-10-02T23:24:52-03:00",
  "data": {
    "created_at": "2026-10-02T23:24:52-03:00",
    "currency": "CAD",
    "customer": {
      "email": "lea.roy@mail.test",
      "name": "Lea Roy",
      "phone": ""
    },
    "delivery": "pickup",
    "id": 1,
    "items": [
      {
        "name": "Cedar candle",
        "price": "20.00",
        "product_id": 1,
        "qty": 2
      }
    ],
    "number": "O-2026-0001",
    "shipping": "0.00",
    "status": "paid",
    "subtotal": "40.00",
    "tax": "0.00",
    "total": "40.00"
  },
  "id": "evt_10",
  "type": "order.paid"
}

Retour à l'index

POST customer.created

Un nouveau client est ajouté. data est un Customer

{
  "business": {
    "id": 2,
    "slug": "salon-ana"
  },
  "created": "2026-10-03T02:24:52.552Z",
  "created_at": "2026-10-02T23:24:52-03:00",
  "data": {
    "company": "",
    "created_at": "2026-10-02T23:24:52-03:00",
    "email": "marie.tremblay@mail.test",
    "id": 2,
    "lang": "fr",
    "marketing_consent": false,
    "name": "Marie Tremblay",
    "notes": "Prefers mornings",
    "phone": "506 555 0123"
  },
  "id": "evt_1",
  "type": "customer.created"
}

Retour à l'index

POST order.created

Une commande est passée, avant son paiement. data est un Order

{
  "business": {
    "id": 2,
    "slug": "salon-ana"
  },
  "created": "2026-10-03T02:24:52.645Z",
  "created_at": "2026-10-02T23:24:52-03:00",
  "data": {
    "created_at": "2026-10-02T23:24:52-03:00",
    "currency": "CAD",
    "customer": {
      "email": "lea.roy@mail.test",
      "name": "Lea Roy",
      "phone": ""
    },
    "delivery": "pickup",
    "id": 1,
    "items": [
      {
        "name": "Cedar candle",
        "price": "20.00",
        "product_id": 1,
        "qty": 2
      }
    ],
    "number": "O-2026-0001",
    "shipping": "0.00",
    "status": "pending_payment",
    "subtotal": "40.00",
    "tax": "0.00",
    "total": "40.00"
  },
  "id": "evt_9",
  "type": "order.created"
}

Retour à l'index

POST invoice.paid

Une facture est marquée comme payée. data est un WebhookInvoice

{
  "business": {
    "id": 2,
    "slug": "salon-ana"
  },
  "created": "2026-10-03T02:24:52.731Z",
  "created_at": "2026-10-02T23:24:52-03:00",
  "data": {
    "base": "510.00",
    "created_at": "2026-10-02T23:24:52-03:00",
    "currency": "CAD",
    "customer": {
      "email": "marie.tremblay@mail.test",
      "name": "Marie Tremblay",
      "phone": null
    },
    "due_date": "2026-11-01",
    "id": 1,
    "lines": [
      {
        "amount": "510.00",
        "concept": "Wedding party",
        "detail": "Hair and make-up, 6 people",
        "qty": 6.0,
        "tax_exempt": false,
        "unit_price": "85.00"
      }
    ],
    "number": "2026-0001",
    "paid_at": "2026-10-02T23:24:52-03:00",
    "status": "paid",
    "tax": "76.37",
    "taxes": [
      {
        "amount": "25.50",
        "name": "GST",
        "rate": 5.0,
        "registration_number": "123456789 RT0001"
      },
      {
        "amount": "50.87",
        "name": "QST",
        "rate": 9.975,
        "registration_number": "1234567890 TQ0001"
      }
    ],
    "total": "586.37"
  },
  "id": "evt_11",
  "type": "invoice.paid"
}

Retour à l'index

Témoins (cookies)

Nous utilisons un témoin pour savoir comment vous nous avez trouvés (un courriel, une recherche ou une annonce) et compter les inscriptions qui en viennent. Si vous acceptez, il garde aussi l'identifiant de clic d'une annonce pendant 90 jours ; si vous refusez, seulement le nom de la campagne. Politique de confidentialité