diff --git a/clients/deduplication-client/package.json b/clients/deduplication-client/package.json index c1853a66..d20c638f 100644 --- a/clients/deduplication-client/package.json +++ b/clients/deduplication-client/package.json @@ -1,6 +1,6 @@ { "name": "@epilot/deduplication-client", - "version": "0.2.5", + "version": "0.3.0", "description": "JavaScript client library for Epilot's Deduplication API", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/clients/deduplication-client/src/openapi-runtime.json b/clients/deduplication-client/src/openapi-runtime.json index a5a1f7a4..fa67319b 100644 --- a/clients/deduplication-client/src/openapi-runtime.json +++ b/clients/deduplication-client/src/openapi-runtime.json @@ -39,6 +39,79 @@ ], "responses": {} } + }, + "/v1/detect-duplicates": { + "post": { + "operationId": "detectDuplicates", + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": {} + } + }, + "/v1/uniqueness-criteria": { + "get": { + "operationId": "listUniquenessCriteria", + "parameters": [ + { + "name": "schema", + "in": "query", + "required": false + } + ], + "responses": {} + }, + "post": { + "operationId": "createUniquenessCriteria", + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": {} + } + }, + "/v1/uniqueness-criteria/{schema}": { + "get": { + "operationId": "getUniquenessCriteria", + "parameters": [ + { + "name": "schema", + "in": "path", + "required": true + } + ], + "responses": {} + }, + "put": { + "operationId": "updateUniquenessCriteria", + "parameters": [ + { + "name": "schema", + "in": "path", + "required": true + } + ], + "requestBody": { + "content": { + "application/json": {} + } + }, + "responses": {} + }, + "delete": { + "operationId": "deleteUniquenessCriteria", + "parameters": [ + { + "name": "schema", + "in": "path", + "required": true + } + ], + "responses": {} + } } }, "components": {}, diff --git a/clients/deduplication-client/src/openapi.d.ts b/clients/deduplication-client/src/openapi.d.ts index 8e6d3406..7b0cfd4c 100644 --- a/clients/deduplication-client/src/openapi.d.ts +++ b/clients/deduplication-client/src/openapi.d.ts @@ -22,10 +22,34 @@ declare namespace Components { */ message: string; } - export type DeduplicateRequestBody = { - toKeep: string; - toDelete: string[]; - }[]; + export type DeduplicateRequestBody = [ + { + /** + * Entity id to keep and merge the duplicates into + */ + toKeep: string; + /** + * Non-empty list of duplicate entity ids to merge into toKeep and delete + */ + toDelete: [ + string, + ...string[] + ]; + }, + ...{ + /** + * Entity id to keep and merge the duplicates into + */ + toKeep: string; + /** + * Non-empty list of duplicate entity ids to merge into toKeep and delete + */ + toDelete: [ + string, + ...string[] + ]; + }[] + ]; export type DeduplicateRequestResponse = /* Base Entity schema */ Entity[]; /** * Represents an async deduplication job @@ -53,6 +77,35 @@ declare namespace Components { */ updatedAt: string; // date-time } + export interface DetectDuplicatesRequestBody { + /** + * Entity schema to search (e.g. 'contact'). Must have UniquenessCriteria configured for the calling org. + */ + schema: string; + /** + * The entity to look up potential duplicates for. Attribute values are extracted from this entity per the schema's match rules; system fields such as '_id' are supported. A rule is evaluated when at least one of its attributes resolves to a non-empty value on this entity; attributes without a value require candidates to also lack a value for them. + */ + entity: { + [name: string]: any; + }; + } + export interface DetectDuplicatesResponse { + matches: DetectedDuplicateMatch[]; + } + export interface DetectedDuplicateMatch { + entity: /* Base Entity schema */ Entity; + /** + * Confidence score for the match, between 0 and 1. + */ + confidence: number; + /** + * Names of the attributes that matched on the rule that produced this hit. + */ + matched_attributes: [ + string, + ...string[] + ]; + } /** * Base Entity schema */ @@ -105,9 +158,95 @@ declare namespace Components { type?: string; } export type JobStatus = "pending" | "processing" | "completed" | "failed"; + /** + * One attribute participating in a match rule. Wrapped as an object so per-attribute options can be added later. + */ + export interface MatchAttribute { + /** + * Name of the entity attribute to match on. Its query path is resolved from the entity schema at query time. + */ + attribute: string; + } + /** + * One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins. + */ + export interface MatchRule { + /** + * Optional human-readable label for the rule. Purely descriptive; not used during matching. + */ + name?: string; + /** + * Attributes that must all match for this rule to fire. Attributes without a value on the source entity must also have no value on a matching candidate. + */ + attributes: [ + /* One attribute participating in a match rule. Wrapped as an object so per-attribute options can be added later. */ MatchAttribute, + .../* One attribute participating in a match rule. Wrapped as an object so per-attribute options can be added later. */ MatchAttribute[] + ]; + /** + * Confidence assigned to matches produced by this rule, between 0 and 1. + */ + confidence: number; + } + /** + * Defines what makes an entity of a given schema unique within an organization. + */ + export interface UniquenessCriteria { + /** + * Unique identifier of the criteria record. + */ + id: string; // uuid + /** + * Organization the criteria belong to. + */ + orgId: string; + /** + * Entity schema these criteria apply to (e.g. 'contact'). + */ + schema: string; + /** + * Ordered list of match rules. Order is the evaluation priority. + */ + matchRules: [ + /* One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins. */ MatchRule, + .../* One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins. */ MatchRule[] + ]; + /** + * ISO 8601 timestamp of record creation. + */ + createdAt: string; // date-time + /** + * ISO 8601 timestamp of last update. + */ + updatedAt: string; // date-time + } + export interface UniquenessCriteriaCreateBody { + /** + * Entity schema these criteria apply to. + */ + schema: string; + matchRules: [ + /* One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins. */ MatchRule, + .../* One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins. */ MatchRule[] + ]; + } + export interface UniquenessCriteriaListResponse { + items: /* Defines what makes an entity of a given schema unique within an organization. */ UniquenessCriteria[]; + } + export interface UniquenessCriteriaUpdateBody { + matchRules: [ + /* One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins. */ MatchRule, + .../* One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins. */ MatchRule[] + ]; + } } } declare namespace Paths { + namespace CreateUniquenessCriteria { + export type RequestBody = Components.Schemas.UniquenessCriteriaCreateBody; + namespace Responses { + export type $201 = /* Defines what makes an entity of a given schema unique within an organization. */ Components.Schemas.UniquenessCriteria; + } + } namespace Deduplicate { export type RequestBody = Components.Schemas.DeduplicateRequestBody; namespace Responses { @@ -120,6 +259,26 @@ declare namespace Paths { export type $202 = /* Response returned immediately when a deduplication job is submitted */ Components.Schemas.DeduplicateAsyncResponse; } } + namespace DeleteUniquenessCriteria { + namespace Parameters { + export type Schema = string; + } + export interface PathParameters { + schema: Parameters.Schema; + } + namespace Responses { + export interface $204 { + } + export interface $404 { + } + } + } + namespace DetectDuplicates { + export type RequestBody = Components.Schemas.DetectDuplicatesRequestBody; + namespace Responses { + export type $200 = Components.Schemas.DetectDuplicatesResponse; + } + } namespace GetDeduplicationJob { namespace Parameters { export type JobId = string; @@ -133,6 +292,44 @@ declare namespace Paths { } } } + namespace GetUniquenessCriteria { + namespace Parameters { + export type Schema = string; + } + export interface PathParameters { + schema: Parameters.Schema; + } + namespace Responses { + export type $200 = /* Defines what makes an entity of a given schema unique within an organization. */ Components.Schemas.UniquenessCriteria; + export interface $404 { + } + } + } + namespace ListUniquenessCriteria { + namespace Parameters { + export type Schema = string; + } + export interface QueryParameters { + schema?: Parameters.Schema; + } + namespace Responses { + export type $200 = Components.Schemas.UniquenessCriteriaListResponse; + } + } + namespace UpdateUniquenessCriteria { + namespace Parameters { + export type Schema = string; + } + export interface PathParameters { + schema: Parameters.Schema; + } + export type RequestBody = Components.Schemas.UniquenessCriteriaUpdateBody; + namespace Responses { + export type $200 = /* Defines what makes an entity of a given schema unique within an organization. */ Components.Schemas.UniquenessCriteria; + export interface $404 { + } + } + } } @@ -167,6 +364,66 @@ export interface OperationMethods { data?: any, config?: AxiosRequestConfig ): OperationResponse + /** + * detectDuplicates - detectDuplicates + * + * Detects potential duplicate entities for the given entity using the schema's prioritized uniqueness rules. Returns matches with a confidence score. + */ + 'detectDuplicates'( + parameters?: Parameters | null, + data?: Paths.DetectDuplicates.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * listUniquenessCriteria - listUniquenessCriteria + * + * Lists UniquenessCriteria for the requesting organization. Optionally filtered by schema. + */ + 'listUniquenessCriteria'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * createUniquenessCriteria - createUniquenessCriteria + * + * Creates a new UniquenessCriteria record. + */ + 'createUniquenessCriteria'( + parameters?: Parameters | null, + data?: Paths.CreateUniquenessCriteria.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * getUniquenessCriteria - getUniquenessCriteria + * + * Fetch a single UniquenessCriteria record. + */ + 'getUniquenessCriteria'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * updateUniquenessCriteria - updateUniquenessCriteria + * + * Replace the matchRules on an existing UniquenessCriteria record. + */ + 'updateUniquenessCriteria'( + parameters?: Parameters | null, + data?: Paths.UpdateUniquenessCriteria.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * deleteUniquenessCriteria - deleteUniquenessCriteria + * + * Delete a UniquenessCriteria record. + */ + 'deleteUniquenessCriteria'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse } export interface PathsDictionary { @@ -206,6 +463,72 @@ export interface PathsDictionary { config?: AxiosRequestConfig ): OperationResponse } + ['/v1/detect-duplicates']: { + /** + * detectDuplicates - detectDuplicates + * + * Detects potential duplicate entities for the given entity using the schema's prioritized uniqueness rules. Returns matches with a confidence score. + */ + 'post'( + parameters?: Parameters | null, + data?: Paths.DetectDuplicates.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/v1/uniqueness-criteria']: { + /** + * listUniquenessCriteria - listUniquenessCriteria + * + * Lists UniquenessCriteria for the requesting organization. Optionally filtered by schema. + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * createUniquenessCriteria - createUniquenessCriteria + * + * Creates a new UniquenessCriteria record. + */ + 'post'( + parameters?: Parameters | null, + data?: Paths.CreateUniquenessCriteria.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + } + ['/v1/uniqueness-criteria/{schema}']: { + /** + * getUniquenessCriteria - getUniquenessCriteria + * + * Fetch a single UniquenessCriteria record. + */ + 'get'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + /** + * updateUniquenessCriteria - updateUniquenessCriteria + * + * Replace the matchRules on an existing UniquenessCriteria record. + */ + 'put'( + parameters?: Parameters | null, + data?: Paths.UpdateUniquenessCriteria.RequestBody, + config?: AxiosRequestConfig + ): OperationResponse + /** + * deleteUniquenessCriteria - deleteUniquenessCriteria + * + * Delete a UniquenessCriteria record. + */ + 'delete'( + parameters?: Parameters | null, + data?: any, + config?: AxiosRequestConfig + ): OperationResponse + } } export type Client = OpenAPIClient @@ -215,5 +538,14 @@ export type DeduplicateAsyncResponse = Components.Schemas.DeduplicateAsyncRespon export type DeduplicateRequestBody = Components.Schemas.DeduplicateRequestBody; export type DeduplicateRequestResponse = Components.Schemas.DeduplicateRequestResponse; export type DeduplicationJob = Components.Schemas.DeduplicationJob; +export type DetectDuplicatesRequestBody = Components.Schemas.DetectDuplicatesRequestBody; +export type DetectDuplicatesResponse = Components.Schemas.DetectDuplicatesResponse; +export type DetectedDuplicateMatch = Components.Schemas.DetectedDuplicateMatch; export type Entity = Components.Schemas.Entity; export type JobStatus = Components.Schemas.JobStatus; +export type MatchAttribute = Components.Schemas.MatchAttribute; +export type MatchRule = Components.Schemas.MatchRule; +export type UniquenessCriteria = Components.Schemas.UniquenessCriteria; +export type UniquenessCriteriaCreateBody = Components.Schemas.UniquenessCriteriaCreateBody; +export type UniquenessCriteriaListResponse = Components.Schemas.UniquenessCriteriaListResponse; +export type UniquenessCriteriaUpdateBody = Components.Schemas.UniquenessCriteriaUpdateBody; diff --git a/clients/deduplication-client/src/openapi.json b/clients/deduplication-client/src/openapi.json index 469d61ce..b6c064a2 100644 --- a/clients/deduplication-client/src/openapi.json +++ b/clients/deduplication-client/src/openapi.json @@ -102,6 +102,193 @@ } } } + }, + "/v1/detect-duplicates": { + "post": { + "operationId": "detectDuplicates", + "summary": "detectDuplicates", + "description": "Detects potential duplicate entities for the given entity using the schema's prioritized uniqueness rules. Returns matches with a confidence score.", + "tags": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DetectDuplicatesRequestBody" + } + } + } + }, + "responses": { + "200": { + "description": "Potential duplicates ranked by rule priority", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DetectDuplicatesResponse" + } + } + } + } + } + } + }, + "/v1/uniqueness-criteria": { + "get": { + "operationId": "listUniquenessCriteria", + "summary": "listUniquenessCriteria", + "description": "Lists UniquenessCriteria for the requesting organization. Optionally filtered by schema.", + "tags": [], + "parameters": [ + { + "name": "schema", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "Filter results to a specific entity schema." + } + ], + "responses": { + "200": { + "description": "Array of UniquenessCriteria records", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UniquenessCriteriaListResponse" + } + } + } + } + } + }, + "post": { + "operationId": "createUniquenessCriteria", + "summary": "createUniquenessCriteria", + "description": "Creates a new UniquenessCriteria record.", + "tags": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UniquenessCriteriaCreateBody" + } + } + } + }, + "responses": { + "201": { + "description": "Created record", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UniquenessCriteria" + } + } + } + } + } + } + }, + "/v1/uniqueness-criteria/{schema}": { + "get": { + "operationId": "getUniquenessCriteria", + "summary": "getUniquenessCriteria", + "description": "Fetch a single UniquenessCriteria record.", + "tags": [], + "parameters": [ + { + "name": "schema", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Entity schema slug." + } + ], + "responses": { + "200": { + "description": "The criteria record", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UniquenessCriteria" + } + } + } + }, + "404": { + "description": "Record not found" + } + } + }, + "put": { + "operationId": "updateUniquenessCriteria", + "summary": "updateUniquenessCriteria", + "description": "Replace the matchRules on an existing UniquenessCriteria record.", + "tags": [], + "parameters": [ + { + "name": "schema", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Entity schema slug." + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UniquenessCriteriaUpdateBody" + } + } + } + }, + "responses": { + "200": { + "description": "Updated record", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UniquenessCriteria" + } + } + } + }, + "404": { + "description": "Record not found" + } + } + }, + "delete": { + "operationId": "deleteUniquenessCriteria", + "summary": "deleteUniquenessCriteria", + "description": "Delete a UniquenessCriteria record.", + "tags": [], + "parameters": [ + { + "name": "schema", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "Entity schema slug." + } + ], + "responses": { + "204": { + "description": "Record deleted" + }, + "404": { + "description": "Record not found" + } + } + } } }, "components": { @@ -120,20 +307,26 @@ "type": "object", "properties": { "toKeep": { - "type": "string" + "type": "string", + "minLength": 1, + "description": "Entity id to keep and merge the duplicates into" }, "toDelete": { "type": "array", "items": { - "type": "string" - } + "type": "string", + "minLength": 1 + }, + "minItems": 1, + "description": "Non-empty list of duplicate entity ids to merge into toKeep and delete" } }, "required": [ "toKeep", "toDelete" ] - } + }, + "minItems": 1 }, "DeduplicateRequestResponse": { "type": "array", @@ -303,6 +496,205 @@ "updatedAt" ], "description": "Represents an async deduplication job" + }, + "DetectDuplicatesRequestBody": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "minLength": 1, + "description": "Entity schema to search (e.g. 'contact'). Must have UniquenessCriteria configured for the calling org." + }, + "entity": { + "type": "object", + "additionalProperties": {}, + "description": "The entity to look up potential duplicates for. Attribute values are extracted from this entity per the schema's match rules; system fields such as '_id' are supported. A rule is evaluated when at least one of its attributes resolves to a non-empty value on this entity; attributes without a value require candidates to also lack a value for them." + } + }, + "required": [ + "schema", + "entity" + ] + }, + "DetectDuplicatesResponse": { + "type": "object", + "properties": { + "matches": { + "type": "array", + "items": { + "$ref": "#/components/schemas/DetectedDuplicateMatch" + } + } + }, + "required": [ + "matches" + ] + }, + "DetectedDuplicateMatch": { + "type": "object", + "properties": { + "entity": { + "$ref": "#/components/schemas/Entity" + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence score for the match, between 0 and 1." + }, + "matched_attributes": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "Names of the attributes that matched on the rule that produced this hit." + } + }, + "required": [ + "entity", + "confidence", + "matched_attributes" + ] + }, + "UniquenessCriteriaListResponse": { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UniquenessCriteria" + } + } + }, + "required": [ + "items" + ] + }, + "UniquenessCriteria": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique identifier of the criteria record." + }, + "orgId": { + "type": "string", + "description": "Organization the criteria belong to." + }, + "schema": { + "type": "string", + "minLength": 1, + "description": "Entity schema these criteria apply to (e.g. 'contact')." + }, + "matchRules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MatchRule" + }, + "minItems": 1, + "description": "Ordered list of match rules. Order is the evaluation priority." + }, + "createdAt": { + "type": "string", + "description": "ISO 8601 timestamp of record creation.", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "description": "ISO 8601 timestamp of last update.", + "format": "date-time" + } + }, + "required": [ + "id", + "orgId", + "schema", + "matchRules", + "createdAt", + "updatedAt" + ], + "description": "Defines what makes an entity of a given schema unique within an organization." + }, + "MatchRule": { + "type": "object", + "properties": { + "name": { + "type": "string", + "maxLength": 100, + "description": "Optional human-readable label for the rule. Purely descriptive; not used during matching." + }, + "attributes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MatchAttribute" + }, + "minItems": 1, + "description": "Attributes that must all match for this rule to fire. Attributes without a value on the source entity must also have no value on a matching candidate." + }, + "confidence": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Confidence assigned to matches produced by this rule, between 0 and 1." + } + }, + "required": [ + "attributes", + "confidence" + ], + "description": "One way to identify the same entity. Evaluated in order; first rule whose attributes are all available and that returns hits wins." + }, + "MatchAttribute": { + "type": "object", + "properties": { + "attribute": { + "type": "string", + "minLength": 1, + "description": "Name of the entity attribute to match on. Its query path is resolved from the entity schema at query time." + } + }, + "required": [ + "attribute" + ], + "description": "One attribute participating in a match rule. Wrapped as an object so per-attribute options can be added later." + }, + "UniquenessCriteriaCreateBody": { + "type": "object", + "properties": { + "schema": { + "type": "string", + "minLength": 1, + "description": "Entity schema these criteria apply to." + }, + "matchRules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MatchRule" + }, + "minItems": 1 + } + }, + "required": [ + "schema", + "matchRules" + ] + }, + "UniquenessCriteriaUpdateBody": { + "type": "object", + "properties": { + "matchRules": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MatchRule" + }, + "minItems": 1 + } + }, + "required": [ + "matchRules" + ] } } },