# API : sync

2 opérations REST du groupe sync.

Base : `/api/v1`. [Conventions](/documentation/api-conventions/) · [Toutes les ressources](/documentation/api-reference/)

- GET /sync/pull : Pull incrémental du briefcase (contexte utilisateur uniquement)
- POST /sync/push : Push d'un batch ordonné de mutations idempotentes
## GET /sync/pull

```json
{
  "summary": "Pull incrémental du briefcase (contexte utilisateur uniquement)",
  "description": "Sans curseur : amorçage complet du briefcase (spec offline-briefcase, filtré record-access + permissions objet). Avec curseur : créations/modifications, retraits de visibilité (removals) et suppressions physiques (tombstones) depuis le dernier pull. Reprise exacte après coupure (le curseur porte la position). Réservé aux sessions utilisateur (§2bis).",
  "tags": [
    "sync"
  ],
  "parameters": [
    {
      "name": "cursor",
      "in": "query",
      "required": false,
      "schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "description": "Curseur opaque du pull précédent",
        "type": "string"
      }
    },
    {
      "name": "limit",
      "in": "query",
      "required": false,
      "schema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "description": "Changes max par page (défaut 200)",
        "type": "integer",
        "minimum": 1,
        "maximum": 500
      }
    }
  ],
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Page de synchronisation",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "changes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "cycle",
                        "businessUnit",
                        "user",
                        "product",
                        "company",
                        "contact",
                        "affiliation",
                        "quote",
                        "salesActivity",
                        "comment",
                        "notification"
                      ]
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "version": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991,
                      "description": "sync_version serveur (T-695) - la base des mutations"
                    },
                    "updatedAt": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "propertyNames": {
                        "type": "string"
                      },
                      "additionalProperties": {},
                      "description": "Formes API v1 de l'objet"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "version",
                    "updatedAt",
                    "data"
                  ],
                  "additionalProperties": false
                }
              },
              "removals": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "cycle",
                        "businessUnit",
                        "user",
                        "product",
                        "company",
                        "contact",
                        "affiliation",
                        "quote",
                        "salesActivity",
                        "comment",
                        "notification"
                      ]
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "required": [
                    "object",
                    "id"
                  ],
                  "additionalProperties": false
                },
                "description": "Sortis du briefcase (visibilité, corbeille, réattribution) - à purger localement"
              },
              "tombstones": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "enum": [
                        "cycle",
                        "businessUnit",
                        "user",
                        "product",
                        "company",
                        "contact",
                        "affiliation",
                        "quote",
                        "salesActivity",
                        "comment",
                        "notification"
                      ]
                    },
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "deletedAt": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "object",
                    "id",
                    "deletedAt"
                  ],
                  "additionalProperties": false
                }
              },
              "cursor": {
                "type": "string"
              },
              "hasMore": {
                "type": "boolean"
              }
            },
            "required": [
              "changes",
              "removals",
              "tombstones",
              "cursor",
              "hasMore"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```

## POST /sync/push

```json
{
  "summary": "Push d'un batch ordonné de mutations idempotentes",
  "description": "Mutations V1 : salesActivity.create/update/transition (done), comment.create, notification.markRead. Chaque mutation porte un id client (journal sync_mutation : rejouer un batch déjà traité est un no-op à réponse identique) ; les updates portent baseVersion - version périmée = fusion par champ T-697 (`merged`, même champ = LWW tracé dans l'historique + perdant notifié ; champ critique = `conflict` strict), refus métier = `rejected` motivé, jamais silencieux. Réservé aux sessions utilisateur (§2bis).",
  "tags": [
    "sync"
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$schema": "https://json-schema.org/draft/2020-12/schema",
          "type": "object",
          "properties": {
            "mutations": {
              "minItems": 1,
              "maxItems": 100,
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "object": {
                    "type": "string",
                    "enum": [
                      "salesActivity",
                      "comment",
                      "notification"
                    ]
                  },
                  "op": {
                    "type": "string",
                    "enum": [
                      "create",
                      "update",
                      "markRead",
                      "transition"
                    ]
                  },
                  "recordId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "baseVersion": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9007199254740991
                  },
                  "data": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "required": [
                  "id",
                  "object",
                  "op"
                ]
              }
            }
          },
          "required": [
            "mutations"
          ]
        }
      }
    }
  },
  "security": [
    {
      "oauth2": []
    },
    {
      "userSession": []
    }
  ],
  "responses": {
    "200": {
      "description": "Réponse par mutation, dans l'ordre du batch",
      "content": {
        "application/json": {
          "schema": {
            "$schema": "https://json-schema.org/draft/2020-12/schema",
            "type": "object",
            "properties": {
              "results": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "applied",
                        "merged",
                        "conflict",
                        "rejected"
                      ]
                    },
                    "recordId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "serverVersion": {
                      "type": "integer",
                      "minimum": -9007199254740991,
                      "maximum": 9007199254740991
                    },
                    "reason": {
                      "type": "string"
                    },
                    "overwrittenFields": {
                      "description": "T-697 : libellés des champs écrasés par une fusion LWW (tracés + notifiés)",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "criticalFields": {
                      "description": "T-697 : champs en résolution stricte à l'origine d'un conflict",
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "id",
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            },
            "required": [
              "results"
            ],
            "additionalProperties": false
          }
        }
      }
    },
    "default": {
      "description": "Erreur - enveloppe problem+json (RFC 9457)",
      "content": {
        "application/problem+json": {
          "schema": {
            "$ref": "#/components/schemas/Problem"
          }
        }
      }
    }
  }
}
```
