openapi: 3.1.0 info: title: Embat AccountingAccounts Attributes API description: Embat API enables connections between any third party application and Embat. Is organized around REST principles, using HTTP responses code and returning data in JSON format. While testing the API, you have to request **sandbox credentials**. contact: name: API Support url: https://embat.io/ email: tech@embat.io version: 2.120.3 x-logo: url: https://storage.googleapis.com/embat-production.appspot.com/assets/embat_dark.svg tags: - name: Attributes description: "`Attribute` represents a custom field that you can define once and then use to tag records across Embat, such as an ERP dimension, a cost center or any other analytic field you want available as a filter in tables, charts and reports. `customId` is the unique identifier of an attribute: set your own value to use as your ERP dimension ID, or let Embat auto-generate one.\n\nAn attribute has a `type` — `list` (a fixed set of `values` to choose from), `string` or `number` (free-form value) — and can optionally be nested under a parent attribute via `parentCustomId` to model hierarchies (e.g. a \"City\" attribute whose values are nested under a \"Country\" attribute's values).\n\nAttribute values are attached to other entities — `Payments`, `Contacts`, `Operations`, `Transactions` and `AccountingEntries` — by sending the attribute's `customId` together with the chosen `value`/`valueCustomId` in that entity's `attributes` field.\n\n**Typical flow:**\n\n1. **Create the attribute** with `POST /attributes/{companyId}`, defining its `type` and, for `list` attributes, its `values`:\n\n```json\nPOST /attributes/{companyId}\n{\n \"customId\": \"cost-center\",\n \"source\": \"erp\",\n \"name\": \"Cost Center\",\n \"type\": \"list\",\n \"values\": [\n { \"customId\": \"marketing\", \"name\": \"Marketing\" },\n { \"customId\": \"sales\", \"name\": \"Sales\" }\n ]\n}\n```\n\n2. **Tag other entities with the attribute.** When creating or updating a payment, contact, operation, transaction or accounting entry, reference the attribute in its `attributes` field:\n\n```json\n{\n \"customId\": \"marketing\",\n \"value\": \"Marketing\"\n}\n```\n\n3. **Maintain the value list** with `POST /attributes/{companyId}/{customId}/values/bulk` to add values without touching the rest of the attribute, or update the attribute directly to replace its full value list.\n" paths: /attributes/{companyId}: get: tags: - Attributes summary: List attributes description: Returns all attributes configured for a company, including their `values` when the attribute is of type `list`. operationId: list_attributes_attributes__companyId__get security: - HTTPBearer: [] parameters: - name: companyId in: path required: true schema: type: string title: Companyid responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ListAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found. The requested resource or `companyId` does not exist. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' post: tags: - Attributes summary: Create attribute description: Creates an attribute. If `customId` is omitted, Embat auto-generates one. If an attribute with the given `customId` already exists, its fields are overwritten instead of raising a duplicate error — this endpoint behaves as an upsert. Sending `values` replaces the attribute's full value list, and **omitting `values` on an existing attribute removes all of its current values** — always resend the values you want to keep. operationId: create_attribute_attributes__companyId__post security: - HTTPBearer: [] parameters: - name: companyId in: path required: true schema: type: string title: Companyid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PostAttributesRequestSchema' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/UpsertAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Company not found, or `parentCustomId` does not match an existing attribute. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' patch: tags: - Attributes summary: Update attributes in bulk description: Updates several attributes in a single call, following the same rules as the single attribute update endpoint. Entries whose `customId` does not match any attribute are silently skipped — the call still returns `200` for the whole batch. operationId: update_attributes_bulk_attributes__companyId__patch security: - HTTPBearer: [] parameters: - name: companyId in: path required: true schema: type: string title: Companyid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BulkPatchAttributesRequestSchema' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BulkUpsertAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Company not found, or a `parentCustomId` does not match an existing attribute. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' delete: tags: - Attributes summary: Delete attributes in bulk description: Deletes several attributes in a single call, following the same rules as the single attribute deletion endpoint. `customId` values that do not match any attribute still return `200` — no `404` is raised — and each returned `id` is derived from the requested `customId`, so an entry in the response does not confirm that an attribute existed or was removed. operationId: delete_attributes_bulk_attributes__companyId__delete security: - HTTPBearer: [] parameters: - name: companyId in: path required: true schema: type: string title: Companyid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BulkDeleteAttributesRequestSchema' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BulkModifyAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found. The requested resource or `companyId` does not exist. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /attributes/{companyId}/{customId}: get: tags: - Attributes summary: Retrieve attribute description: Returns a single attribute by `customId`. operationId: retrieve_attribute_attributes__companyId___customId__get security: - HTTPBearer: [] parameters: - name: customId in: path required: true schema: type: string title: Customid - name: companyId in: path required: true schema: type: string title: Companyid responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/GetAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Company not found, or no attribute matches the given `customId`. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' patch: tags: - Attributes summary: Update attribute description: Updates an attribute identified by `customId`. Only the fields sent in the request are changed; fields left out keep their current value. If `values` is sent, it **replaces** the attribute's full value list — any previously stored value not included is removed (omit `values` entirely to leave the current values untouched). Updating a `customId` that does not match any attribute returns `200` without applying any change — no `404` is raised. operationId: update_attribute_attributes__companyId___customId__patch security: - HTTPBearer: [] parameters: - name: customId in: path required: true schema: type: string title: Customid - name: companyId in: path required: true schema: type: string title: Companyid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/PatchAttributesRequestSchema' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/UpsertAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Company not found, or `parentCustomId` does not match an existing attribute. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' delete: tags: - Attributes summary: Delete attribute description: Deletes an attribute by `customId`, together with all of its values, and clears the `parentId`/`parentCustomId` of any attribute nested under it. Deleting a `customId` that does not match any attribute still returns `200` — no `404` is raised — and the `id` returned in that case is derived from the requested `customId`, so it does not confirm that an attribute existed or was removed. operationId: delete_attribute_attributes__companyId___customId__delete security: - HTTPBearer: [] parameters: - name: customId in: path required: true schema: type: string title: Customid - name: companyId in: path required: true schema: type: string title: Companyid responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/ModifyAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found. The requested resource or `companyId` does not exist. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /attributes/{companyId}/bulk: post: tags: - Attributes summary: Create attributes in bulk description: Creates several attributes in a single call, following the same rules as the single attribute creation endpoint (upsert by `customId`; omitting `values` on an existing attribute removes all of its current values). operationId: create_attributes_bulk_attributes__companyId__bulk_post security: - HTTPBearer: [] parameters: - name: companyId in: path required: true schema: type: string title: Companyid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BulkPostAttributesRequestSchema' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BulkUpsertAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Company not found, or a `parentCustomId` does not match an existing attribute. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /attributes/{companyId}/{customId}/values/bulk: post: tags: - Attributes summary: Add values to an attribute description: Adds values to an existing attribute, identified by `customId`, without affecting its other values. If a value with the same `customId` already exists on the attribute, it is replaced. This endpoint does not verify that the attribute exists beforehand. operationId: add_attribute_values_attributes__companyId___customId__values_bulk_post security: - HTTPBearer: [] parameters: - name: customId in: path required: true schema: type: string title: Customid - name: companyId in: path required: true schema: type: string title: Companyid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BulkPostAttributesValuesRequestSchema' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BulkUpsertAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found. The requested resource or `companyId` does not exist. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /attributes/{companyId}/{customId}/values: delete: tags: - Attributes summary: Remove values from an attribute description: Removes one or more values from an attribute, identified by `customId`. Values not found on the attribute are silently ignored — the call still returns `200`. The `id` returned for each entry is the value's `customId` echoed back, not a generated Embat ID. operationId: remove_attribute_values_attributes__companyId___customId__values_delete security: - HTTPBearer: [] parameters: - name: customId in: path required: true schema: type: string title: Customid - name: companyId in: path required: true schema: type: string title: Companyid requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/BulkDeleteAttributesRequestSchema' responses: '200': description: Successful Response content: application/json: schema: $ref: '#/components/schemas/BulkModifyAttributesResponseSchema' '401': description: Unauthorized. The bearer token is missing, invalid or expired. content: application/json: example: detail: user not authorized schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Not found. The requested resource or `companyId` does not exist. content: application/json: example: detail: 0021 companyId not found schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Unexpected error. Contact support if it persists. content: application/json: example: detail: Internal server error schema: $ref: '#/components/schemas/ErrorResponse' '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' components: schemas: BulkDeleteAttributesRequestSchema: properties: data: items: $ref: '#/components/schemas/DeleteAttributesRequestSchema' type: array title: Data description: Attributes or values to remove, identified by `customId`. type: object required: - data title: BulkDeleteAttributesRequestSchema ValidationError: properties: loc: items: anyOf: - type: string - type: integer type: array title: Location msg: type: string title: Message type: type: string title: Error Type input: title: Input ctx: type: object title: Context type: object required: - loc - msg - type title: ValidationError BulkPostAttributesValuesRequestSchema: properties: data: items: $ref: '#/components/schemas/AttributesRequestValuesSchema' type: array title: Data description: Values to add to the attribute. type: object required: - data title: BulkPostAttributesValuesRequestSchema SourceEnum: type: string enum: - erp - api - embat title: SourceEnum DeleteAttributesRequestSchema: properties: customId: type: string title: Customid description: 'Custom ID to remove: the attribute''s `customId` when deleting attributes, or a value''s `customId` when removing values from an attribute.' type: object required: - customId title: DeleteAttributesRequestSchema ModifyAttributesResponseSchema: properties: id: type: string title: Id description: Embat resource ID type: object required: - id title: ModifyAttributesResponseSchema GetAttributesResponseSchema: properties: customId: anyOf: - type: string - type: 'null' title: Customid description: Your own unique ID for the attribute. If omitted, Embat auto-generates one. examples: - cost-center source: anyOf: - $ref: '#/components/schemas/SourceEnum' - type: 'null' description: Origin of the attribute record. Defaults to `embat` when not stored on the record. active: type: boolean title: Active description: Whether the attribute is active. default: true name: type: string title: Name description: Display name of the attribute. examples: - Cost Center type: anyOf: - $ref: '#/components/schemas/AttributesStatusEnum' - type: 'null' description: 'Data type of the attribute''s values: `list`, `string` or `number`.' required: type: boolean title: Required description: 'Whether a value for this attribute should be mandatory wherever it is used. Informational only: this API does not enforce it.' default: false values: anyOf: - items: $ref: '#/components/schemas/AttributesResponseValuesSchema' type: array - type: 'null' title: Values description: Values available for this attribute. parentCustomId: anyOf: - type: string - type: 'null' title: Parentcustomid description: Custom ID of the parent attribute this attribute is nested under. id: type: string title: Id description: Embat attribute ID. createdAt: type: string format: date-time title: Createdat description: Creation date of the attribute. updatedAt: type: string format: date-time title: Updatedat description: Last modification date of the attribute. parentId: anyOf: - type: string - type: 'null' title: Parentid description: Embat ID of the parent attribute. Only present when the attribute is nested under another one via `parentCustomId`. companyId: type: string title: Companyid description: Embat company ID. You can get them from "companies" endpoints type: object required: - name - id - createdAt - updatedAt - companyId title: GetAttributesResponseSchema BulkPostAttributesRequestSchema: properties: data: items: $ref: '#/components/schemas/PostAttributesRequestSchema' type: array title: Data description: Attributes to create. type: object required: - data title: BulkPostAttributesRequestSchema BulkModifyAttributesResponseSchema: properties: data: items: $ref: '#/components/schemas/ModifyAttributesResponseSchema' type: array title: Data description: Result of the bulk operation, one entry per item. type: object required: - data title: BulkModifyAttributesResponseSchema UpsertAttributesResponseSchema: properties: id: type: string title: Id description: Embat resource ID customId: type: string title: Customid description: Client-provided custom ID type: object required: - id - customId title: UpsertAttributesResponseSchema ListAttributesResponseSchema: properties: data: items: $ref: '#/components/schemas/GetAttributesResponseSchema' type: array title: Data description: All attributes of the company. type: object required: - data title: ListAttributesResponseSchema AttributesStatusEnum: type: string enum: - list - string - number title: AttributesStatusEnum AttributesResponseValuesSchema: properties: customId: anyOf: - type: string - type: 'null' title: Customid description: Your own unique ID for the value. If omitted, Embat auto-generates one. examples: - madrid id: type: string title: Id description: Embat ID of the value. name: type: string title: Name description: Display name of the value. examples: - Madrid parentCustomId: anyOf: - type: string - type: 'null' title: Parentcustomid description: Custom ID of the value, within the parent attribute (see the attribute's `parentCustomId`), that this value is nested under. examples: - spain parentId: anyOf: - type: string - type: 'null' title: Parentid description: Embat ID of the parent value. Only present when `parentCustomId` matched an existing value of the parent attribute at the time this value was saved. type: object required: - id - name title: AttributesResponseValuesSchema AuxBulkPatchAttributesRequestSchema: properties: name: anyOf: - type: string - type: 'null' title: Name description: Display name of the attribute. active: type: boolean title: Active description: Whether the attribute is active. Omit to leave the current value unchanged. default: true values: anyOf: - items: $ref: '#/components/schemas/AttributesRequestValuesSchema' type: array - type: 'null' title: Values description: 'Full list of values the attribute should have after this update. Sending `values` **replaces** the current list: any previously stored value whose `customId` is not included here is removed. Omit `values` entirely to leave the current values untouched. An attribute holds at most 5000 values; if the combined total would exceed the limit, the excess new values are silently discarded and existing ones already in the list are kept.' parentCustomId: anyOf: - type: string - type: 'null' title: Parentcustomid description: Custom ID of the parent attribute, to nest this attribute under another one (e.g. a "City" attribute nested under "Country"). Must reference an existing attribute. examples: - country customId: type: string title: Customid description: Custom ID of the attribute to update. examples: - cost-center type: object required: - customId title: AuxBulkPatchAttributesRequestSchema PatchAttributesRequestSchema: properties: name: anyOf: - type: string - type: 'null' title: Name description: Display name of the attribute. active: type: boolean title: Active description: Whether the attribute is active. Omit to leave the current value unchanged. default: true values: anyOf: - items: $ref: '#/components/schemas/AttributesRequestValuesSchema' type: array - type: 'null' title: Values description: 'Full list of values the attribute should have after this update. Sending `values` **replaces** the current list: any previously stored value whose `customId` is not included here is removed. Omit `values` entirely to leave the current values untouched. An attribute holds at most 5000 values; if the combined total would exceed the limit, the excess new values are silently discarded and existing ones already in the list are kept.' parentCustomId: anyOf: - type: string - type: 'null' title: Parentcustomid description: Custom ID of the parent attribute, to nest this attribute under another one (e.g. a "City" attribute nested under "Country"). Must reference an existing attribute. examples: - country type: object title: PatchAttributesRequestSchema PostAttributesRequestSchema: properties: customId: anyOf: - type: string - type: 'null' title: Customid description: Your own unique ID for the attribute. If omitted, Embat auto-generates one. examples: - cost-center source: $ref: '#/components/schemas/SourceEnum' description: Origin of the attribute record. active: type: boolean title: Active description: Whether the attribute is active. default: true name: type: string title: Name description: Display name of the attribute. examples: - Cost Center type: $ref: '#/components/schemas/AttributesStatusEnum' description: 'Data type of the attribute''s values: `list` (a fixed set of `values` to choose from), `string` or `number` (free-form value, no `values` needed).' required: type: boolean title: Required description: 'Whether a value for this attribute should be mandatory wherever it is used. Informational only: this API does not enforce it.' default: false values: anyOf: - items: $ref: '#/components/schemas/AttributesRequestValuesSchema' type: array - type: 'null' title: Values description: Values available for this attribute (relevant when `type` is `list`). If an attribute with this `customId` already exists, sending `values` **replaces** its current list — any previously stored value not included here is removed. Omitting `values` when creating a new attribute with an existing `customId` also removes all of its current values. An attribute holds at most 5000 values; if the combined total would exceed the limit, the excess new values are silently discarded. parentCustomId: anyOf: - type: string - type: 'null' title: Parentcustomid description: Custom ID of the parent attribute, to nest this attribute under another one (e.g. a "City" attribute nested under "Country"). Must reference an existing attribute. examples: - country type: object required: - source - name - type title: PostAttributesRequestSchema ErrorResponse: properties: detail: type: string title: Detail description: Human-readable explanation of the error. examples: - user not authorized type: object required: - detail title: ErrorResponse description: Error payload returned by the API (FastAPI `detail` convention). HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError BulkPatchAttributesRequestSchema: properties: data: items: $ref: '#/components/schemas/AuxBulkPatchAttributesRequestSchema' type: array title: Data description: Attributes to update, identified by `customId`. type: object required: - data title: BulkPatchAttributesRequestSchema BulkUpsertAttributesResponseSchema: properties: data: items: $ref: '#/components/schemas/UpsertAttributesResponseSchema' type: array title: Data description: Result of the bulk operation, one entry per attribute. type: object required: - data title: BulkUpsertAttributesResponseSchema AttributesRequestValuesSchema: properties: customId: type: string title: Customid description: Your own unique ID for the value, unique within the attribute. examples: - madrid name: type: string title: Name description: Display name of the value. examples: - Madrid parentCustomId: anyOf: - type: string - type: 'null' title: Parentcustomid description: Custom ID of the value of the parent attribute (see the attribute's `parentCustomId`) that this value is nested under. Ignored if the attribute has no `parentCustomId` or no value with this `customId` exists yet on the parent attribute. examples: - spain type: object required: - customId - name title: AttributesRequestValuesSchema securitySchemes: HTTPBearer: type: http scheme: bearer