openapi: 3.0.3 info: title: QUIZ AMOCRM integration description: Интеграция с Амо. Ключевая задача - создавать заявки в соответствующей воронкой подключенного аккаунта version: 1.0.0 tags: - name: main description: Операции связанные с AmoCRM paths: /account: post: operationId: ConnectAccount description: подключение аккаунта амо к аккаунту quiz. На вход получает только токен. На выход отдаёт ссылку для подключения. Создаёт модель аккаунта, имеющую связь с основным аккаунтом tags: - main responses: '200': description: успешное создание ссылки для авторизации content: 'application/json': schema: $ref: '#/components/schemas/ConnectAccountResp' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' delete: operationId: SoftDeleteAccount description: мягкое удаление аккаунта. Юзер должен иметь возможность создать новый аккаунт, взамен удалённого tags: - main responses: '200': $ref: '#/components/responses/200' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' get: operationId: GetCurrentAccount description: получение текущего аккаунта, компании текщего пользователя tags: - main responses: '200': description: аккаунт интеграции амо content: 'application/json': schema: $ref: '#/components/schemas/AccountAmo' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '500': $ref: '#/components/responses/500' /webhook/create: get: operationId: WebhookCreate description: это метод для получения пары токенов для аккаунта. Пары токенов стоит хранить в отдельной таблице и завести воркер, который будет обновлять рефреш. https://www.amocrm.ru/developers/content/oauth/step-by-step - вот дока для этого метода tags: - main responses: '200': description: Success /webhook/delete: get: operationId: WebhookDelete description: это метод для оповещения об удалении итеграции из учетки в амо. При его вызове надо мягко удалить соответствующий аккаунт. https://www.amocrm.ru/developers/content/oauth/step-by-step#%D0%A5%D1%83%D0%BA-%D0%BE%D0%B1-%D0%BE%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B8-%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D0%B8 tags: - main responses: '200': description: Success /users: get: operationId: GettingUserWithPagination tags: - main description: получение списка юзеров для текущего пользователя и его компании, закешированных у нас, с пагинацией https://www.amocrm.ru/developers/content/crm_platform/users-api#users-list parameters: - in: query name: Pagination description: Параметры пагинации required: false schema: type: object properties: page: type: integer description: Номер страницы пагинации. Если не указан, используется значение по умолчанию. example: 1 size: type: integer description: Размер страницы пагинации. Если не указан, используется значение по умолчанию. example: 25 required: - page - size responses: '200': description: успешное получение списка пользователей для текущего пользователя и его компании content: 'application/json': schema: $ref: "#/components/schemas/UserListResp" '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' patch: operationId: UpdateListUsers description: обновление списка юзеров tags: - main responses: '200': $ref: '#/components/responses/200' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' /pipelines: get: operationId: GetPipelinesWithPagination tags: - main description: получение списка воронок, закешированных у нас, с пагинацией https://www.amocrm.ru/developers/content/crm_platform/leads_pipelines parameters: - in: query name: Pagination description: Параметры пагинации required: false schema: type: object properties: page: type: integer description: Номер страницы пагинации. Если не указан, используется значение по умолчанию. example: 1 size: type: integer description: Размер страницы пагинации. Если не указан, используется значение по умолчанию. example: 25 required: - page - size responses: '200': description: успешное получение списка воронок content: 'application/json': schema: $ref: "#/components/schemas/UserListPipelinesResp" '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' patch: operationId: UpdateListPipelines description: обновление списка воронок tags: - main responses: '200': $ref: '#/components/responses/200' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' /steps: get: operationId: GetStepsWithPagination tags: - main description: получение списка этапов воронок, закешированных у нас, с пагинацией https://www.amocrm.ru/developers/content/crm_platform/leads_pipelines#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D1%81%D1%82%D0%B0%D1%82%D1%83%D1%81%D0%BE%D0%B2-%D0%B2%D0%BE%D1%80%D0%BE%D0%BD%D0%BA%D0%B8-%D1%81%D0%B4%D0%B5%D0%BB%D0%BE%D0%BA parameters: - in: query name: Pagination description: Параметры пагинации required: false schema: type: object properties: pipelineID: type: integer description: id воронки которой принадлежат шаги example: 123 page: type: integer description: Номер страницы пагинации. Если не указан, используется значение по умолчанию. example: 1 size: type: integer description: Размер страницы пагинации. Если не указан, используется значение по умолчанию. example: 25 required: - pipelineID - page - size responses: '200': description: успешное получение списка шагов воронок content: 'application/json': schema: $ref: "#/components/schemas/UserListStepsResp" '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' patch: operationId: UpdateListSteps description: обновление списка этапов воронок tags: - main responses: '200': $ref: '#/components/responses/200' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' /fields: get: operationId: GetFieldsWithPagination tags: - main description: получение списка кастомных полей, закешированных у нас, с пагинацией https://www.amocrm.ru/developers/content/crm_platform/custom-fields#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D0%BF%D0%BE%D0%BB%D0%B5%D0%B9-%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D0%B8 parameters: - in: query name: Pagination description: Параметры пагинации required: false schema: type: object properties: page: type: integer description: Номер страницы пагинации. Если не указан, используется значение по умолчанию. example: 1 size: type: integer description: Размер страницы пагинации. Если не указан, используется значение по умолчанию. example: 25 required: - page - size responses: '200': description: успешное получение списка тегов content: 'application/json': schema: $ref: "#/components/schemas/UserListFieldsResp" '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' patch: operationId: UpdateListCustom description: обновление списка кастомных полей tags: - main responses: '200': $ref: '#/components/responses/200' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' /tags: get: operationId: GetTagsWithPagination tags: - main description: получение списка тегов, закешированных у нас, с пагинацией https://www.amocrm.ru/developers/content/crm_platform/tags-api#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D1%82%D0%B5%D0%B3%D0%BE%D0%B2-%D0%B4%D0%BB%D1%8F-%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D0%B8 parameters: - in: query name: Pagination description: Параметры пагинации required: false schema: type: object properties: page: type: integer description: Номер страницы пагинации. Если не указан, используется значение по умолчанию. example: 1 size: type: integer description: Размер страницы пагинации. Если не указан, используется значение по умолчанию. example: 25 required: - page - size responses: '200': description: успешное получение списка тегов content: 'application/json': schema: $ref: "#/components/schemas/UserListTagsResp" '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' patch: operationId: UpdateListTags description: обновление списка тегов tags: - main responses: '200': $ref: '#/components/responses/200' '401': $ref: '#/components/responses/401' '500': $ref: '#/components/responses/500' # таких запросах для блупринта обязательно нужно указывать параметры /rules/{quizID}: get: operationId: GettingQuizRules tags: - main description: получение настроек интеграции для конкретного квиза parameters: - in: path name: quizID required: true schema: type: string description: Id квиза responses: '200': description: успешное получение настройки интеграции content: 'application/json': schema: $ref: "#/components/schemas/Rule" '400': $ref: '#/components/responses/400' '404': $ref: '#/components/responses/404' '500': $ref: '#/components/responses/500' post: operationId: SetQuizSettings description: создание настроек интеграции для конкретного квиза, при успешном исходе кладет задачу в кафку, на 1 квиз 1 правило tags: - main parameters: - in: path name: quizID required: true schema: type: string description: Id квиза requestBody: content: application/json: schema: $ref: "#/components/schemas/RulesReq" responses: '200': $ref: '#/components/responses/200' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '500': $ref: '#/components/responses/500' patch: operationId: ChangeQuizSettings description: изменение настроек интеграции для конкретного квиза, при успешном исходе кладет задачу в кафку, на 1 квиз 1 правило tags: - main parameters: - in: path name: quizID required: true schema: type: string description: Id квиза requestBody: content: application/json: schema: $ref: "#/components/schemas/RulesReq" responses: '200': $ref: '#/components/responses/200' '400': $ref: '#/components/responses/400' '401': $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' '500': $ref: '#/components/responses/500' components: schemas: Rule: type: object description: объект настройки правил сохранения данных в амо properties: ID: type: integer description: айдишник в нашей системе Primary Key AccountID: type: integer description: связь с аккаунтом в интеграции амо id в амо QuizID: type: integer description: айдишник опроса PerformerID: type: integer description: айдишник ответственного за сделку PipelineID: type: integer description: айдишник воронки StepID: type: integer description: айдишник этапа FieldsRule: type: object description: правила заполнения полей сущностей в амо properties: lead: $ref: '#/components/schemas/FieldRule' contact: $ref: '#/components/schemas/ContactRules' company: $ref: '#/components/schemas/FieldRule' customer: $ref: '#/components/schemas/FieldRule' TagsToAdd: type: object properties: Lead: type: array items: type: integer format: int64 description: Массив ID тегов для Leads, теги с id который наш Primary Contact: type: array items: type: integer format: int64 description: Массив ID тегов для Contacts, теги с id который наш Primary Company: type: array items: type: integer format: int64 description: Массив ID тегов для Company, теги с id который наш Primary Customer: type: array items: type: integer format: int64 description: Массив ID тегов для Customer, теги с id который наш Primary example: Lead: [ 101, 102, 103 ] Contact: [ 201, 202, 203 ] Company: [ 301, 302, 303 ] Customer: [ 401, 402, 403 ] Deleted: type: boolean description: флаг мягкого удаления CreatedAt: type: integer description: таймштамп создания воронки в нашей системе FieldRule: type: object description: правила сопоставления вопроса полю properties: QuestionID: type: integer additionalProperties: type: integer description: сопоставление айдишника вопроса полю, которое будет заполняться ответом. соответственно QuestionID это айдишник вопроса. это я так мэпу пытался записать. Мапа, где ключи - QuestionID, значения - ID кастомного поля Pipeline: type: object description: объект воронки амо properties: ID: type: integer description: айдишник в нашей системе Primary Key AmoID: type: integer description: айдишник воронки в амо AccountID: type: integer description: связь с аккаунтом в интеграции амо id аккаунта в амо Name: type: string description: название воронки в амо IsArchive: type: boolean description: флаг архивной воронки в амо Deleted: type: boolean description: флаг мягкого удаления CreatedAt: type: integer description: таймштамп создания воронки в нашей системе Step: type: object description: объект шага воронки амо properties: ID: type: integer description: айдишник в нашей системе Primary Key AmoID: type: integer description: айдишник шага воронки в амо PipelineID: type: integer description: айдишник воронки в амо AccountID: type: integer description: связь с аккаунтом в интеграции амо id в амо Name: type: string description: название воронки в амо Color: type: string description: цвет шага в амо Deleted: type: boolean description: флаг мягкого удаления CreatedAt: type: integer description: таймштамп создания воронки в нашей системе Field: type: object description: объект кастомного поля амо properties: ID: type: integer description: айдишник в нашей системе Primary Key AmoID: type: integer description: айдишник кастомного поля в амо Code: type: string description: кодовое слово в амо AccountID: type: integer description: связь с аккаунтом в интеграции амо id аккаунта в амо Name: type: string description: название воронки в амо EntityType: type: string description: тип сущности в амо, для которой это кастомное поле Type: type: string description: тип поля https://www.amocrm.ru/developers/content/crm_platform/custom-fields#%D0%94%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%BD%D1%8B%D0%B5-%D1%82%D0%B8%D0%BF%D1%8B-%D0%BF%D0%BE%D0%BB%D0%B5%D0%B9 Deleted: type: boolean description: флаг мягкого удаления CreatedAt: type: integer description: таймштамп создания воронки в нашей системе UTM: type: object description: объект настройки UTM, данные о которых мы сохраняем в амо properties: ID: type: integer description: айдишник в нашей системе Primary Key AmoFieldID: type: integer description: айдишник кастомного поля в амо QuizID: type: integer description: айдишник квиза AccountID: type: integer description: связь с аккаунтом в интеграции амо id амо Name: type: string description: название тега в амо Deleted: type: boolean description: флаг мягкого удаления CreatedAt: type: integer description: таймштамп создания тега в нашей системе Tag: type: object description: объект тега из амо properties: ID: type: integer description: айдишник в нашей системе Primary Key AmoID: type: integer description: айдишник тега в амо AccountID: type: integer description: связь с аккаунтом в интеграции амо id аккаунта в амо Entity: type: string description: сущность, к которой принадлежит этот тег. Наверное, стоит сделать через enum в базе Name: type: string description: название тега в амо Color: type: string description: цвет тега в амо Deleted: type: boolean description: флаг мягкого удаления CreatedAt: type: integer description: таймштамп создания тега в нашей системе AccountAmo: type: object description: модель основного аккаунта "компании" амо properties: id: type: integer format: int64 description: postgres big serial accountID: type: string description: ID аккаунта нашей системы amoID: type: integer format: int32 description: ID компании в AmoCRM name: type: string description: Название компании deleted: type: boolean description: Флаг, указывающий на удаление createdAt: type: string format: date-time description: Время создания subdomain: type: string description: Поддомен компании в амо country: type: string description: Страна driveURL: type: string description: URL объектного хранилища stale: type: boolean description: флаг "не свежести" если с токенами все в порядке - false, если просрочились то true UserAmoAccount: type: object description: объект пользователя аккаунта амо, который находится под компанией которая подключилась properties: id: type: integer format: int64 description: postgres big serial amoID: type: integer format: int32 description: ID компании в амо, к которой пользователь принадлежит amoUserID: type: integer format: int32 description: ID пользователя в амо name: type: string description: Имя email: type: string description: Email role: type: integer format: int32 description: Роль group: type: integer format: int32 description: Группа deleted: type: boolean description: Флаг, указывающий на удаление createdAt: type: string format: date-time description: Время создания записи ConnectAccountResp: type: object properties: link: type: string description: ссылка для авторизации в амо GetListUserUTMResp: type: object properties: count: type: integer description: общее количество юзеров, которые у нас закешированы для этого пользователя items: type: array description: список юзеров, которые были закешированы нашим сервисом items: $ref: "#/components/schemas/UTM" SaveUserListUTMReq: type: object properties: utms: type: array description: список utm для сохранения. сохранять только те, которых в этом аккаунте ещё нет items: $ref: "#/components/schemas/UTM" ListSavedIDUTMResp: type: object properties: IDs: type: array description: список айдишников сохранённых меток items: type: string ListDeleteUTMIDsReq: type: object properties: utms: type: array description: список айдишников utm которые удалить items: type: integer UserListResp: type: object properties: count: type: integer description: общее количество юзеров, которые у нас закешированы для этого пользователя и его компании items: type: array description: список юзеров, которые были закешированы нашим сервисом items: $ref: "#/components/schemas/UserAmoAccount" UserListPipelinesResp: type: object properties: count: type: integer description: общее количество воронок, которые у нас закешированы для этого пользователя items: type: array description: список воронок, которые были закешированы нашим сервисом items: $ref: "#/components/schemas/Pipeline" UserListStepsResp: type: object properties: count: type: integer description: общее количество шагов воронок, которые у нас закешированы для этого пользователя items: type: array description: список шагов воронок, которые были закешированы нашим сервисом items: $ref: "#/components/schemas/Step" UserListFieldsResp: type: object properties: count: type: integer description: общее количество кастомных полей, которые у нас закешированы для этого пользователя items: type: array description: список кастомных полей, которые были закешированы нашим сервисом items: $ref: "#/components/schemas/Field" UserListTagsResp: type: object properties: count: type: integer description: общее количество тегов, которые у нас закешированы для этого пользователя items: type: array description: список тегов, которые были закешированы нашим сервисом items: $ref: "#/components/schemas/Tag" PaginationReq: type: object properties: page: type: integer description: указание страницы пагинации. Если страница не указана, применять 0 size: type: integer description: указание размера страницы пагинации. По умолчанию применять 25 RulesReq: type: object properties: PerformerID: type: integer description: "айдишник ответственного за сделку" PipelineID: type: integer description: "айдишник воронки" StepID: type: integer description: "айдишник этапа" Fieldsrule: type: object properties: Lead: $ref: '#/components/schemas/FieldRule' Contact: $ref: '#/components/schemas/ContactRules' Company: $ref: '#/components/schemas/FieldRule' Customer: $ref: '#/components/schemas/FieldRule' TagsToAdd: type: object properties: Lead: type: array items: type: integer format: int64 description: Массив ID тегов для Leads, теги с id который наш Primary Contact: type: array items: type: integer format: int64 description: Массив ID тегов для Contacts, теги с id который наш Primary Company: type: array items: type: integer format: int64 description: Массив ID тегов для Company, теги с id который наш Primary Customer: type: array items: type: integer format: int64 description: Массив ID тегов для Customer, теги с id который наш Primary example: Lead: [ 101, 102, 103 ] Contact: [ 201, 202, 203 ] Company: [ 301, 302, 303 ] Customer: [ 401, 402, 403 ] ContactRules: type: object description: правила заполнения сущности контакта, название поля = id кастомного поля в амо properties: ContactRuleMap: type: string additionalProperties: type: integer QuestionID: type: integer additionalProperties: type: integer description: сопоставление айдишника вопроса полю, которое будет заполняться ответом. соответственно QuestionID это айдишник вопроса. это я так мэпу пытался записать. Мапа, где ключи - QuestionID, значения - ID кастомного поля responses: '200': description: Success content: application/json: schema: type: string description: Success '201': description: Created content: application/json: schema: type: string description: Created '204': description: No content content: application/json: schema: type: string description: No content '400': description: Bad Request content: application/json: schema: type: string description: Bad Request '401': description: Unauthorized content: application/json: schema: type: string description: Unauthorized '403': description: Forbidden content: application/json: schema: type: string description: Forbidden '404': description: Not Found content: application/json: schema: type: string description: Not Found '500': description: Internal Server Error content: application/json: schema: type: string description: Internal Server Error