arazzo: 1.0.1 info: title: Flutterwave Upsert Customer And Charge summary: Search for a customer by email, create one only if missing, then charge that customer and verify it. description: >- A deduplication-aware collection flow. The workflow searches for an existing customer by email and branches: when no match is found it creates a new customer, and when a match is found it reuses the existing customer id. It then initiates a charge against whichever customer id was resolved and retrieves the charge to confirm its final status. This avoids creating duplicate customer records on repeat purchases. Every step spells out its request inline so the flow can be read and executed without opening the underlying OpenAPI description. version: 1.0.0 sourceDescriptions: - name: paymentsApi url: ../openapi/flutterwave-payments-api-openapi.yml type: openapi workflows: - workflowId: upsert-customer-and-charge summary: Resolve or create a customer by email, then charge them with verification. description: >- Searches for the customer by email, creates one when absent, then charges the resolved customer id and branches on the verified charge status. inputs: type: object required: - accessToken - email - amount - currency properties: accessToken: type: string description: OAuth2 client-credentials bearer token for the Authorization header. email: type: string description: Email address used to find or create the customer. amount: type: number description: Amount to charge in the major currency unit. currency: type: string description: ISO currency code for the charge. reference: type: string description: Optional merchant reference to correlate the charge. steps: - stepId: findCustomer description: Search for an existing customer by email before creating one. operationId: searchCustomers parameters: - name: Authorization in: header value: "Bearer $inputs.accessToken" requestBody: contentType: application/json payload: email: $inputs.email successCriteria: - condition: $statusCode == 200 outputs: matchedCustomerId: $response.body#/data/0/id onSuccess: - name: customerExists type: goto stepId: chargeCustomer criteria: - context: $response.body condition: $.data.length > 0 type: jsonpath - name: customerMissing type: goto stepId: createCustomer criteria: - context: $response.body condition: $.data.length == 0 type: jsonpath - stepId: createCustomer description: Create a new customer when no existing record matched the email. operationId: createCustomer parameters: - name: Authorization in: header value: "Bearer $inputs.accessToken" requestBody: contentType: application/json payload: email: $inputs.email successCriteria: - condition: $statusCode == 201 outputs: newCustomerId: $response.body#/id - stepId: chargeCustomer description: Charge the resolved customer, whether found or newly created. operationId: createCharge parameters: - name: Authorization in: header value: "Bearer $inputs.accessToken" requestBody: contentType: application/json payload: amount: $inputs.amount currency: $inputs.currency reference: $inputs.reference customer: email: $inputs.email successCriteria: - condition: $statusCode == 201 outputs: chargeId: $response.body#/id - stepId: verifyCharge description: Retrieve the charge to confirm its final status. operationId: getCharge parameters: - name: Authorization in: header value: "Bearer $inputs.accessToken" - name: id in: path value: $steps.chargeCustomer.outputs.chargeId successCriteria: - condition: $statusCode == 200 outputs: chargeStatus: $response.body#/status onSuccess: - name: chargeSucceeded type: end criteria: - context: $response.body condition: $.status == "succeeded" type: jsonpath - name: chargeFailed type: end criteria: - context: $response.body condition: $.status == "failed" type: jsonpath outputs: matchedCustomerId: $steps.findCustomer.outputs.matchedCustomerId newCustomerId: $steps.createCustomer.outputs.newCustomerId chargeId: $steps.chargeCustomer.outputs.chargeId chargeStatus: $steps.verifyCharge.outputs.chargeStatus