> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sync2books.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Issue a credit note

> Reverses an accepted sale **in full**. The buyer and lines are copied from the sale, so you send only the sale id, your own number and a return date. A sale can be credited once. The status codes work as for `POST /v1/sales`: `201` accepted, `202` in flight, `422` rejected, and `200` with `Idempotent-Replayed: true` for a repeated request.

Required scope: `sales:write`.



## OpenAPI

````yaml /openapi/etims.json post /v1/credit-notes
openapi: 3.1.0
info:
  title: Sync2Books Compliance API (eTIMS)
  version: 1.0.0
  description: >-
    Register items, issue sales and credit notes, record stock and read supplier
    invoices for a Kenyan business, with every fiscal document signed by KRA
    eTIMS.


    Authenticate with an API key from the compliance dashboard, sent in the
    `x-api-key` header or as a bearer token. A `cmp_sk_test_...` key acts on
    sandbox businesses and a `cmp_sk_live_...` key on production ones; both use
    the same base URL.


    New here? Start with the [eTIMS quickstart](/etims-quickstart). The
    conventions every endpoint shares are in [Authentication & API
    keys](/etims-authentication), [Errors & Troubleshooting](/etims-errors),
    [Idempotency](/etims-idempotency) and [Rate limits](/etims-rate-limits).


    This is a separate product from the [Accounting API](/api-reference), with
    its own keys.
servers:
  - url: https://sync2books-compliance-api.apps.kintro.money
    description: >-
      Sync2Books Compliance API. The key you use decides whether a call reaches
      the KRA sandbox or production.
security:
  - ApiKeyAuth: []
  - BearerAuth: []
tags:
  - name: Identity
    description: Check what a key can do.
  - name: Businesses
    description: The businesses and branches a key can act for.
  - name: Items
    description: >-
      Create items and register them with KRA. An item must be registered before
      it can be sold.
  - name: Stock
    description: Record stock movements and report them to KRA.
  - name: Sales
    description: Issue sales, read them back and download KRA-signed receipts.
  - name: Credit notes
    description: Reverse an accepted sale in full.
  - name: Purchases
    description: Supplier invoices KRA holds against the business.
  - name: Lookups
    description: KRA code lists and item classifications.
paths:
  /v1/credit-notes:
    post:
      tags:
        - Credit notes
      summary: Issue a credit note
      description: >-
        Reverses an accepted sale **in full**. The buyer and lines are copied
        from the sale, so you send only the sale id, your own number and a
        return date. A sale can be credited once. The status codes work as for
        `POST /v1/sales`: `201` accepted, `202` in flight, `422` rejected, and
        `200` with `Idempotent-Replayed: true` for a repeated request.


        Required scope: `sales:write`.
      operationId: createCreditNote
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreditNoteRequest'
            examples:
              refund:
                summary: Refund a sale
                value:
                  traderInvoiceNumber: CN-2026-0001
                  returnDate: '2026-10-03'
                  saleId: sale_example_1
                  reason: '06'
      responses:
        '200':
          description: >-
            A repeat of an earlier request. The original credit note is returned
            and nothing is filed again.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
            Idempotent-Replayed:
              $ref: '#/components/headers/IdempotentReplayed'
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: object
                    properties:
                      sale:
                        $ref: '#/components/schemas/Sale'
              example:
                data:
                  sale:
                    id: sale_example_2
                    type: credit_note
                    status: completed
                    traderInvoiceNumber: CN-2026-0001
                    saleDate: '2026-10-03'
                    paymentTypeCode: '01'
                    customer:
                      name: Example Customer Ltd
                      pin: P000000000X
                      phone: null
                      email: null
                    lines:
                      - id: line_example_1
                        itemId: itm_example_1
                        name: 500ml Cooking Oil
                        description: 500ml Cooking Oil
                        quantity: -2
                        unitPrice: 3500
                        total: -7000
                        taxableAmount: -6034.48
                        taxAmount: -965.52
                        taxRate: 16
                        taxTypeCode: B
                    totals:
                      total: -7000
                      taxableAmount: -6034.48
                      taxAmount: -965.52
                    receipt:
                      cuInvoiceNo: KRACU0000000000/13 NC
                      receiptNumber: 13
                      receiptLabel: NC
                      scuId: KRACU0000000000
                      scuDate: 02/10/2026
                      scuTime: '10:15:30'
                      totalReceiptCounter: '13'
                      signature: AAAA-BBBB-CCCC
                      internalData: DDDD-EEEE-FFFF
                      verificationUrl: https://etims-verify.example/receipt?id=EXAMPLE
                      originalCuInvoiceNo: KRACU0000000000/12 NS
                    originalSaleId: sale_example_1
                    error: null
                    callback: null
        '201':
          description: >-
            KRA accepted the credit note. The response key is `sale`, with
            `type: "credit_note"`.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: object
                    properties:
                      sale:
                        $ref: '#/components/schemas/Sale'
              example:
                data:
                  sale:
                    id: sale_example_2
                    type: credit_note
                    status: completed
                    traderInvoiceNumber: CN-2026-0001
                    saleDate: '2026-10-03'
                    paymentTypeCode: '01'
                    customer:
                      name: Example Customer Ltd
                      pin: P000000000X
                      phone: null
                      email: null
                    lines:
                      - id: line_example_1
                        itemId: itm_example_1
                        name: 500ml Cooking Oil
                        description: 500ml Cooking Oil
                        quantity: -2
                        unitPrice: 3500
                        total: -7000
                        taxableAmount: -6034.48
                        taxAmount: -965.52
                        taxRate: 16
                        taxTypeCode: B
                    totals:
                      total: -7000
                      taxableAmount: -6034.48
                      taxAmount: -965.52
                    receipt:
                      cuInvoiceNo: KRACU0000000000/13 NC
                      receiptNumber: 13
                      receiptLabel: NC
                      scuId: KRACU0000000000
                      scuDate: 02/10/2026
                      scuTime: '10:15:30'
                      totalReceiptCounter: '13'
                      signature: AAAA-BBBB-CCCC
                      internalData: DDDD-EEEE-FFFF
                      verificationUrl: https://etims-verify.example/receipt?id=EXAMPLE
                      originalCuInvoiceNo: KRACU0000000000/12 NS
                    originalSaleId: sale_example_1
                    error: null
                    callback: null
        '202':
          description: The credit note has not reached a result yet.
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/RateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/RateLimitRemaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/RateLimitReset'
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: object
                    properties:
                      sale:
                        $ref: '#/components/schemas/Sale'
              example:
                data:
                  sale:
                    id: sale_example_2
                    type: credit_note
                    status: retrying
                    traderInvoiceNumber: CN-2026-0001
                    saleDate: '2026-10-03'
                    paymentTypeCode: '01'
                    customer:
                      name: Example Customer Ltd
                      pin: P000000000X
                      phone: null
                      email: null
                    lines:
                      - id: line_example_1
                        itemId: itm_example_1
                        name: 500ml Cooking Oil
                        description: 500ml Cooking Oil
                        quantity: -2
                        unitPrice: 3500
                        total: -7000
                        taxableAmount: -6034.48
                        taxAmount: -965.52
                        taxRate: 16
                        taxTypeCode: B
                    totals:
                      total: -7000
                      taxableAmount: -6034.48
                      taxAmount: -965.52
                    receipt: null
                    originalSaleId: sale_example_1
                    error: null
                    callback: null
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          description: The request conflicts with an existing document.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                already_credited:
                  summary: already_credited
                  value:
                    error:
                      code: already_credited
                      message: >-
                        This sale has already been credited by credit note
                        CN-2026-0001. A credit note reverses a sale in full, so
                        it can only be issued once.
                      creditNoteId: sale_example_2
                credit_note_in_progress:
                  summary: credit_note_in_progress
                  value:
                    error:
                      code: credit_note_in_progress
                      message: >-
                        Credit note CN-2026-0001 for this sale has not reached a
                        result from KRA yet. Wait for it, or re-drive it with
                        POST /v1/sales/{id}/retry, instead of issuing another.
                      creditNoteId: sale_example_2
        '422':
          description: The document was not accepted by KRA, or could not be submitted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                not_a_sale:
                  summary: not_a_sale
                  value:
                    error:
                      code: not_a_sale
                      message: >-
                        A credit note can only reverse a sale, not another
                        credit note.
                sale_not_accepted:
                  summary: sale_not_accepted
                  value:
                    error:
                      code: sale_not_accepted
                      message: >-
                        Only a sale KRA has accepted can be credited. Retry or
                        fix the sale first.
                kra_rejected:
                  summary: kra_rejected
                  value:
                    error:
                      code: kra_rejected
                      message: The KRA reason for the rejection.
                      sale:
                        id: sale_example_2
                        type: credit_note
                        status: failed
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: >-
        A unique value you choose for this document, 8 to 128 characters:
        letters, digits and `. _ : -`. Repeating the request with the same key
        returns the original result instead of filing a second document.
        Strongly recommended.
      schema:
        type: string
        minLength: 8
        maxLength: 128
        pattern: ^[A-Za-z0-9._:-]+$
      example: order-10042-attempt-1
  schemas:
    CreditNoteRequest:
      type: object
      required:
        - traderInvoiceNumber
        - returnDate
        - saleId
      properties:
        traderInvoiceNumber:
          type: string
          maxLength: 50
          description: Your own number for the credit note.
        returnDate:
          type: string
          format: date
          description: As `YYYY-MM-DD`.
        saleId:
          type: string
          description: The id of the accepted sale to reverse.
        reason:
          type: string
          enum:
            - '01'
            - '02'
            - '03'
            - '04'
            - '05'
            - '06'
          default: '06'
          description: >-
            `01` missing quantity, `02` missing data, `03` damaged, `04` wasted,
            `05` raw material shortage, `06` refund.
        callbackUrl:
          $ref: '#/components/schemas/CallbackUrl'
        businessId:
          type: string
          description: >-
            The business to act for. Required for organisation-wide keys; omit
            it for a business-bound key. List the ids you can use with `GET
            /v1/businesses`.
    Sale:
      type: object
      description: A sale or a credit note. On a credit note the amounts are negative.
      properties:
        id:
          type: string
        type:
          type: string
          enum:
            - sale
            - credit_note
        status:
          type: string
          enum:
            - pending
            - ready_to_submit
            - retrying
            - completed
            - failed
            - cancelled
          description: >-
            `completed` means KRA accepted the document. `pending`,
            `ready_to_submit` and `retrying` are still in flight.
        traderInvoiceNumber:
          type: string
        saleDate:
          type:
            - string
            - 'null'
          format: date
        paymentTypeCode:
          type:
            - string
            - 'null'
        customer:
          $ref: '#/components/schemas/Customer'
        lines:
          type: array
          items:
            $ref: '#/components/schemas/SaleLine'
        totals:
          type: object
          properties:
            total:
              type: number
            taxableAmount:
              type: number
            taxAmount:
              type: number
        receipt:
          $ref: '#/components/schemas/Receipt'
        originalSaleId:
          type:
            - string
            - 'null'
          description: On a credit note, the id of the sale it reverses.
        error:
          type:
            - string
            - 'null'
          description: Why the document failed. Set only when `status` is `failed`.
        callback:
          $ref: '#/components/schemas/Callback'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          additionalProperties: true
          properties:
            code:
              type: string
              description: >-
                A stable, machine-readable code. Branch on this. See [Errors &
                Troubleshooting](/etims-errors) for the full list.
              examples:
                - invalid_request
                - kra_rejected
                - already_credited
            message:
              type: string
              description: >-
                A human-readable explanation. The wording can change; do not
                parse it.
          description: >-
            Some errors carry extra fields next to `code` and `message`, for
            example `sale`, `item`, `errors`, `creditNoteId` or `branches`.
    CallbackUrl:
      type: string
      maxLength: 2048
      description: >-
        Where to send the result. An absolute `https` URL on a public host, with
        no credentials in it. See [Result callbacks](/etims-callbacks).
    Customer:
      type: object
      properties:
        name:
          type:
            - string
            - 'null'
        pin:
          type:
            - string
            - 'null'
        phone:
          type:
            - string
            - 'null'
        email:
          type:
            - string
            - 'null'
    SaleLine:
      type: object
      properties:
        id:
          type: string
        itemId:
          type: string
        name:
          type:
            - string
            - 'null'
        description:
          type:
            - string
            - 'null'
        quantity:
          type: number
        unitPrice:
          type: number
        total:
          type: number
          description: Tax-inclusive line total.
        taxableAmount:
          type: number
          description: The part of the total that is subject to tax.
        taxAmount:
          type: number
        taxRate:
          type: number
          description: The VAT rate in percent.
        taxTypeCode:
          type:
            - string
            - 'null'
          description: The KRA tax type letter of the item.
    Receipt:
      type:
        - object
        - 'null'
      description: >-
        The KRA-signed receipt values. `null` until KRA has accepted the
        document.
      properties:
        cuInvoiceNo:
          type:
            - string
            - 'null'
          description: The control unit invoice number printed on the receipt.
        receiptNumber:
          type:
            - integer
            - 'null'
        receiptLabel:
          type:
            - string
            - 'null'
          description: For example `NS` for a sale and `NC` for a credit note.
        scuId:
          type:
            - string
            - 'null'
          description: Printed on the receipt.
        scuDate:
          type:
            - string
            - 'null'
          description: Printed on the receipt, as `DD/MM/YYYY`.
        scuTime:
          type:
            - string
            - 'null'
          description: Printed on the receipt, as `hh:mm:ss`.
        totalReceiptCounter:
          type:
            - string
            - 'null'
        signature:
          type:
            - string
            - 'null'
        internalData:
          type:
            - string
            - 'null'
          description: Printed on the receipt.
        verificationUrl:
          type:
            - string
            - 'null'
          description: >-
            The KRA page that verifies the receipt. The QR code on the PDF
            points here.
        originalCuInvoiceNo:
          type:
            - string
            - 'null'
          description: On a credit note, the CU invoice number of the sale it reverses.
    Callback:
      type:
        - object
        - 'null'
      description: >-
        Delivery state of the result callback. `null` when the sale was created
        without a `callbackUrl`.
      properties:
        url:
          type: string
        status:
          type: string
          enum:
            - awaiting_outcome
            - pending
            - delivered
            - failed
        event:
          type:
            - string
            - 'null'
          enum:
            - sale.completed
            - sale.failed
            - null
        attempts:
          type: integer
        lastAttemptAt:
          type:
            - string
            - 'null'
          format: date-time
        lastResponseStatus:
          type:
            - integer
            - 'null'
        lastError:
          type:
            - string
            - 'null'
        deliveredAt:
          type:
            - string
            - 'null'
          format: date-time
        nextAttemptAt:
          type:
            - string
            - 'null'
          format: date-time
  headers:
    RateLimitLimit:
      description: Requests allowed per minute for your application.
      schema:
        type: integer
    RateLimitRemaining:
      description: Requests left in the current one-minute window.
      schema:
        type: integer
    RateLimitReset:
      description: >-
        Seconds until the current window resets. This is a number of seconds,
        not a Unix timestamp.
      schema:
        type: integer
    IdempotentReplayed:
      description: >-
        Always `true`. Present only when the response is an earlier result
        returned for a repeated `Idempotency-Key`.
      schema:
        type: string
        enum:
          - 'true'
  responses:
    BadRequest:
      description: >-
        The request is malformed. The message names the first field that is
        wrong.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            invalid_request:
              summary: invalid_request
              value:
                error:
                  code: invalid_request
                  message: lines[0].quantity must be greater than 0
    Unauthorized:
      description: >-
        The key is missing, malformed, revoked, expired or belongs to a
        suspended application. The response never says which.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            invalid_api_key:
              summary: invalid_api_key
              value:
                error:
                  code: invalid_api_key
                  message: Invalid API key
    Forbidden:
      description: >-
        The key is valid but may not do this: a missing scope, a business the
        key is not limited to, or a test key used against a production business
        (or the reverse).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missing_scope:
              summary: missing_scope
              value:
                error:
                  code: forbidden
                  message: This API key is missing the sales:write scope
            other_business:
              summary: other_business
              value:
                error:
                  code: forbidden
                  message: >-
                    This API key is limited to a single business and cannot act
                    for another one.
            environment_mismatch:
              summary: environment_mismatch
              value:
                error:
                  code: forbidden
                  message: >-
                    This is a test API key and Example Business Ltd is a
                    production business. Use the key for that environment.
    NotFound:
      description: >-
        The id does not exist, or belongs to another business. The two cases are
        deliberately indistinguishable.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            not_found:
              summary: not_found
              value:
                error:
                  code: not_found
                  message: Sale sale_example_9 not found
    RateLimited:
      description: >-
        The application has used its requests for this minute. Wait
        `Retry-After` seconds.
      headers:
        X-RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
        Retry-After:
          description: Seconds to wait before trying again.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            rate_limited:
              summary: rate_limited
              value:
                error:
                  code: rate_limited
                  message: >-
                    Rate limit of 120 requests per minute exceeded. Retry in
                    23s.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your API key, for example `cmp_sk_test_xxxxxxxxxxxxxxxxxxxxxxxx`. Create
        one on the Integrations page of the compliance dashboard.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: cmp_sk_...
      description: >-
        The same key, sent as `Authorization: Bearer <key>`. Use this if your
        HTTP client makes custom headers awkward.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.