From c7da5b4cde212e11475dcc754b0a0a0d5e6a987a Mon Sep 17 00:00:00 2001 From: salmonumbrella <182032677+salmonumbrella@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:30:46 -0800 Subject: [PATCH] chore(docs): Add contact merge endpoint to swagger documentation (#13172) ## Summary This PR adds API documentation for the contact merge endpoint: `POST /api/v1/accounts/{account_id}/actions/contact_merge` This endpoint allows merging two contacts into one. The base contact survives and receives all data from the mergee contact, which is then deleted. ## Changes - Added `swagger/paths/application/contacts/merge.yml` with complete endpoint documentation - Updated `swagger/paths/index.yml` to include the new endpoint ## Related Issues Closes chatwoot/docs#243 --------- Co-authored-by: Pranav --- swagger/paths/application/contacts/merge.yml | 55 ++++++++++++ swagger/paths/index.yml | 6 ++ swagger/swagger.json | 88 ++++++++++++++++++++ swagger/tag_groups/application_swagger.json | 88 ++++++++++++++++++++ 4 files changed, 237 insertions(+) create mode 100644 swagger/paths/application/contacts/merge.yml diff --git a/swagger/paths/application/contacts/merge.yml b/swagger/paths/application/contacts/merge.yml new file mode 100644 index 000000000..2c5057837 --- /dev/null +++ b/swagger/paths/application/contacts/merge.yml @@ -0,0 +1,55 @@ +tags: + - Contacts +operationId: contactMerge +summary: Merge Contacts +security: + - userApiKey: [] +description: | + Merge two contacts into a single contact. The base contact remains and receives all + data from the mergee contact. After the merge, the mergee contact is permanently deleted. + + This action is irreversible. All conversations, labels, and custom attributes from the + mergee contact will be moved to the base contact. +requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - base_contact_id + - mergee_contact_id + properties: + base_contact_id: + type: integer + description: ID of the contact that will remain after the merge and receive all data + example: 1 + mergee_contact_id: + type: integer + description: ID of the contact that will be merged into the base contact and deleted + example: 2 +responses: + '200': + description: Contacts merged successfully + content: + application/json: + schema: + $ref: '#/components/schemas/contact_base' + '400': + description: Bad request - invalid contact IDs or contacts cannot be merged + content: + application/json: + schema: + $ref: '#/components/schemas/bad_request_error' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/bad_request_error' + '404': + description: One or both contacts not found + content: + application/json: + schema: + $ref: '#/components/schemas/bad_request_error' diff --git a/swagger/paths/index.yml b/swagger/paths/index.yml index d5126a8d1..9d6ee2430 100644 --- a/swagger/paths/index.yml +++ b/swagger/paths/index.yml @@ -275,6 +275,12 @@ /api/v1/accounts/{account_id}/contacts/{id}/contactable_inboxes: $ref: ./application/contactable_inboxes/get.yml +# Contact Merge +/api/v1/accounts/{account_id}/actions/contact_merge: + parameters: + - $ref: '#/components/parameters/account_id' + post: + $ref: ./application/contacts/merge.yml # Automation Rule /api/v1/accounts/{account_id}/automation_rules: diff --git a/swagger/swagger.json b/swagger/swagger.json index 8d539c259..c210ba716 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -3424,6 +3424,94 @@ } } }, + "/api/v1/accounts/{account_id}/actions/contact_merge": { + "parameters": [ + { + "$ref": "#/components/parameters/account_id" + } + ], + "post": { + "tags": [ + "Contacts" + ], + "operationId": "contactMerge", + "summary": "Merge Contacts", + "security": [ + { + "userApiKey": [] + } + ], + "description": "Merge two contacts into a single contact. The base contact remains and receives all\ndata from the mergee contact. After the merge, the mergee contact is permanently deleted.\n\nThis action is irreversible. All conversations, labels, and custom attributes from the\nmergee contact will be moved to the base contact.\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "base_contact_id", + "mergee_contact_id" + ], + "properties": { + "base_contact_id": { + "type": "integer", + "description": "ID of the contact that will remain after the merge and receive all data", + "example": 1 + }, + "mergee_contact_id": { + "type": "integer", + "description": "ID of the contact that will be merged into the base contact and deleted", + "example": 2 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Contacts merged successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/contact_base" + } + } + } + }, + "400": { + "description": "Bad request - invalid contact IDs or contacts cannot be merged", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/bad_request_error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/bad_request_error" + } + } + } + }, + "404": { + "description": "One or both contacts not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/bad_request_error" + } + } + } + } + } + } + }, "/api/v1/accounts/{account_id}/automation_rules": { "parameters": [ { diff --git a/swagger/tag_groups/application_swagger.json b/swagger/tag_groups/application_swagger.json index 2fd0cbdee..59849ea5a 100644 --- a/swagger/tag_groups/application_swagger.json +++ b/swagger/tag_groups/application_swagger.json @@ -1967,6 +1967,94 @@ } } }, + "/api/v1/accounts/{account_id}/actions/contact_merge": { + "parameters": [ + { + "$ref": "#/components/parameters/account_id" + } + ], + "post": { + "tags": [ + "Contacts" + ], + "operationId": "contactMerge", + "summary": "Merge Contacts", + "security": [ + { + "userApiKey": [] + } + ], + "description": "Merge two contacts into a single contact. The base contact remains and receives all\ndata from the mergee contact. After the merge, the mergee contact is permanently deleted.\n\nThis action is irreversible. All conversations, labels, and custom attributes from the\nmergee contact will be moved to the base contact.\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "base_contact_id", + "mergee_contact_id" + ], + "properties": { + "base_contact_id": { + "type": "integer", + "description": "ID of the contact that will remain after the merge and receive all data", + "example": 1 + }, + "mergee_contact_id": { + "type": "integer", + "description": "ID of the contact that will be merged into the base contact and deleted", + "example": 2 + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Contacts merged successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/contact_base" + } + } + } + }, + "400": { + "description": "Bad request - invalid contact IDs or contacts cannot be merged", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/bad_request_error" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/bad_request_error" + } + } + } + }, + "404": { + "description": "One or both contacts not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/bad_request_error" + } + } + } + } + } + } + }, "/api/v1/accounts/{account_id}/automation_rules": { "parameters": [ {