# Complete a redaction job Learn how to complete your first redaction job. This example uses redaction jobs to redact a customer’s personal data. This removes your access to that data in the Stripe API and Dashboard. ## Create your first job and redacting a test customer The [RedactionJob](https://docs.stripe.com/api/privacy/redaction-job.md) object is the primary object you interact with and is the core abstraction to manage all redaction requests. You can use the RedactionJob object to indicate objects of interest, validate them to make sure they’re eligible, and then execute the redaction. ```curl curl https://api.stripe.com/v1/privacy/redaction_jobs \ -u "<>:" \ -d "objects[customers][]=cus_1xx" \ -d "objects[customers][]=cus_2xx" ``` After you create a job, it begins to validate the eligibility of the provided objects for redaction. For `Customer` objects, the redaction job identifies all related objects to that customer, including PaymentIntents, Charges, Subscriptions, Invoices, PaymentMethods, notifications, and so on. Some of these objects can have hundreds of records, directly correlated to how frequently a customer can make purchases or add payment details. While you can specify additional identifiers for objects owned by the same customer, you don’t need to explicitly define them. We have a limit of 10 object identifiers to redact in each new job. ## Set up a customer with test data Before creating a redaction job, start by creating a test customer in test mode. Go to the [Stripe Dashboard](https://dashboard.stripe.com/test/customers), click **Add customer**, and fill out some test information in the dialog. After creating the customer, copy the `cus_` ID. You can use the Stripe Dashboard or API to create any additional objects your Stripe integration uses, such as `PaymentIntents`, `Charges`, `PaymentMethods`, recurring `Subscriptions`, and so on. We create a basic unconfirmed `PaymentIntent` for this `Customer` object like the following: ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d "objects[amount]=999" \ -d "objects[currency]=usd" \ -d "objects[customer]=ADD_CUS_ID_HERE" \ -d "objects[description]=Test charge" ``` See the [PaymentIntents integration guide](https://docs.stripe.com/payments/payment-intents.md#creating-a-paymentintent) for more information. In this first run, you leave this PaymentIntent incomplete to demonstrate a capability of the job later on. If you view the customer in the Dashboard, you can see something like the following: ![Unconfirmed payment in Dashboard](https://b.stripecdn.com/docs-statics-srv/assets/payment-in-dashboard.67647e73eec0ab69a78848e01b057293.png) Unconfirmed payment in Dashboard ## Create a redaction job Now that you have a Customer with some additional redactable objects, create a redaction job with the test customer ID. The request looks like the following: ```curl curl https://api.stripe.com/v1/privacy/redaction_jobs \ -u "<>:" \ -d "objects[customers][]=ADD_CUS_ID_HERE" ``` ```json { "id": "prj_xxx", "object": "privacy.redaction_job", "created": 1234567890, "livemode": false,"status": "validating", "validation_behavior": "error" } ``` By default, `validation_behavior` is set to `error`. This is configurable and more details are available in the next steps in the guide. ## View the Redaction Job object When the status of a job changes, Stripe sends a webhook. You can view [webhook events](https://dashboard.stripe.com/test/events) in the Stripe Dashboard. See the [webhook documentation](https://docs.stripe.com/webhooks.md#webhook-endpoint-def) for more details. You can also use [Retrieve a redaction job](https://docs.stripe.com/api/privacy/redaction-job/retrieve.md) to check the status of the job: ```curl curl https://api.stripe.com/v1/privacy/redaction_jobs/prj_xxx \ -u "<>:" ``` You’ll see the job in a `validating` status, which means the job is currently checking whether the provided object and related objects are eligible for redaction. This process can take some time, depending on how many objects are related to the provided object. If the job finds no errors or restrictions, the status changes to `ready`. Otherwise, it changes to `failed`. If you created the PaymentIntent earlier and left it as incomplete, you’ll see a status of `failed`. ## Check for validation errors If a job fails, you can check for the list of errors using the validation errors endpoint. You’ll see the following response from the incomplete PaymentIntent that you created earlier. ```curl curl https://api.stripe.com/v1/privacy/redaction_jobs/prj_xxx/validation_errors \ -u "<>:" ``` ```json { "object": "list", "data": [ { "id": "prjve_123", "object": "privacy.redaction_job_validation_error", "code": "invalid_state", "erroring_object": { "id": "pi_123", "object_type": "payment_intent" }, "message": "PaymentIntent is not finalized. Confirm or cancel the PaymentIntent." } ], "has_more": false, "url": "/v1/privacy/redaction_jobs/:job/validation_errors" } ``` The error messages tell you why you can’t redact an object. These restrictions are a mix of whether we can support redaction of the object and product behavior. Redacting some objects might have different outcomes, so some action on your part is necessary before you can redact the objects. In this example, you can take the required action using the Stripe API or Dashboard by confirming or canceling the PaymentIntent. Depending on your use case, if you don’t have a business reason to maintain the customer’s data, you can use the redaction job validation behavior to automatically apply our recommended fixes. ## Validation behavior We have two modes of validation behavior, `error` and `fix`. You can update the mode as follows: ```curl curl https://api.stripe.com/v1/privacy/redaction_jobs/prj_xxx \ -u "<>:" \ -d validation_behavior=fix ``` ```json { "id": "prj_xxx", "object": "privacy.redaction_job", "created": 1234567890, "livemode": false, "status": "failed","validation_behavior": "fix" } ``` You can also set the `validation_behavior` back to `error` if desired using: ```curl curl https://api.stripe.com/v1/privacy/redaction_jobs/prj_xxx \ -u "<>:" \ -d validation_behavior=error ``` Setting the validation behavior only changes the configuration and doesn’t change anything else. The fix action applies when running the job. Treat the fix validation as destructive behavior. You can view [the list of fixes](https://docs.stripe.com/privacy/redaction.md#fix-validation-behaviors) and what fixes they apply. ## Validate a redaction job again When a job fails to validate, it remains in a `failed` status. After you address all validation errors, either through `validation_behavior: fix` or manual changes, validate the job. ```curl curl -X POST https://api.stripe.com/v1/privacy/redaction_jobs/prj_xxx/validate \ -u "<>:" ``` ```json { "id": "prj_xxx", "object": "privacy.redaction_job", "created": 1234567890, "livemode": false,"status": "validating", "validation_behavior": "fix" } ``` In the PaymentIntent example, using fix validation behavior resolves the validation error. If you’re trying to redact objects in other Stripe products, repeat [the step](https://docs.stripe.com/privacy/redaction/example.md#validation-errors) to check for validation errors until you resolve all validation errors, and the status of the job becomes `ready`. ```curl curl https://api.stripe.com/v1/privacy/redaction_jobs/prj_xxx \ -u "<>:" ``` ```json { "id": "prj_xxx", "object": "privacy.redaction_job", "created": 1234567890, "livemode": false,"status": "ready", "validation_behavior": "fix" } ``` ## Run a redaction job After the job is in a `ready` status, you can run it. This puts your job into a `redacting` status. No further action is necessary. ```curl curl -X POST https://api.stripe.com/v1/privacy/redaction_jobs/prj_xxx/run \ -u "<>:" ``` ```json { "id": "prj_xxx", "object": "privacy.redaction_job", "created": 1234567890, "livemode": false,"status": "redacting", "validation_behavior": "fix" } ``` After the validation is completed, the status transitions to `succeeded`. ```json { "id": "prj_xxx", "object": "privacy.redaction_job", "created": 1234567890, "livemode": false,"status": "succeeded", "validation_behavior": "fix" } ``` You’ll also see the related objects redacted from the Dashboard and API. ```curl curl https://api.stripe.com/v1/customers/cus_xxx \ -u "<>:" ``` ```json { "id": "cus_xxx", "object": "customer","deleted": true } ``` ```curl curl https://api.stripe.com/v1/payment_intents/pi_xxx \ -u "<>:" ``` ```json { "id": "pi_xxx", "object": "payment_intent", "amount": 999, ... "amount_received": 999, ... "confirmation_method": "automatic", "created": 1234567890, "currency": "usd", "customer": "cus_xxx","description": "[redacted]", "last_payment_error": null, "latest_charge": "ch_xxx", ... "payment_method": "pm_xxx", "payment_method_configuration_details": { "id": "pmc_xxx", "parent": null }, ... } ``` ## Cancel a redaction job At any point after validating and before redacting, you can cancel the job and abandon all changes. Only one job can interact with an object at a time, so creating multiple jobs directly or implicitly redacting the same object results in an error for the later jobs. Canceling a job releases the object and allows other jobs to redact the object again. The example job with the PaymentIntent has already run, so you can’t cancel that job. To test this, [create a new redaction job](https://docs.stripe.com/privacy/redaction/example.md#create-job) and cancel like the following: ```curl curl -X POST https://api.stripe.com/v1/privacy/redaction_jobs/A_DIFFERENT_REDACTION_JOB_ID/cancel \ -u "<>:" ``` If you see a validation error that says “This object is being processed by another active job," you can release the objects by canceling that job. ## Find a customer To redact information related to a person, identify their associated `Customer` object identifier. You can find this using the [Customer Search endpoint](https://docs.stripe.com/api/customers/search.md), the [Customer page on the Dashboard](https://dashboard.stripe.com/customers), or the search bar in the Dashboard near the top of the page. After you find the customer, copy their ID. If you’re using the Dashboard, you can click just below **Customer ID** to copy it. ## See also - [Redact personal data](https://docs.stripe.com/privacy/redaction.md) - [Redaction Jobs API reference](https://docs.stripe.com/api/privacy/redaction-job.md) - [Handling customer deletion requests](https://docs.stripe.com/privacy/deletion-requests.md)