Shopify created_at vs processed_at: Which Order Date Is Which
In Shopify, created_at (createdAt) is set when the customer completes checkout and never changes. processed_at (processedAt) is when the order was processed. It can be set to an earlier date for imported or backdated orders, and Shopify says it's the date shown on your orders and used in analytics reports. For a normal checkout the two are identical.
- createdAt is set when checkout completes and stays the same for the life of the order.
- processedAt is the date Shopify shows on orders and uses in analytics reports, according to Shopify's API docs.
- Imported orders can carry a past processedAt, so their two dates differ by days or years.
- The GraphQL orders query sorts by PROCESSED_AT by default, but you can filter and sort by created_at instead.
- The admin's CSV export has a Created at column but no processed date column, so imported orders can look wrong in exports.
Every Shopify order stores two order dates. created_at (createdAt in GraphQL) is the moment the order entered Shopify, set when the customer completes checkout and never changed afterwards. processed_at (processedAt) is when the order was processed, and Shopify's API docs say it's the date that appears on your orders and the one used in analytics reports. On a normal online order the two are the same to the second. They only split apart when an order is imported, created through the API with an earlier date, or backdated, and that's when the difference starts to matter for reports, exports and integrations.
This guide covers what each field means, where each one shows up, how they behave in the API, and a simple rule for which one to use.
What is the difference between created_at and processed_at in Shopify?
created_at records when Shopify created the order record. processed_at records when the sale happened. Shopify keeps them separate so an order can be added to Shopify today but still be dated to when it was really sold.
Here's how Shopify's GraphQL Admin API documents the order's timestamps:
| Field (GraphQL / REST) | What Shopify's docs say | Can it change? | Typical use |
|---|---|---|---|
createdAt / created_at | Set when the customer completes checkout and unchanged throughout the order's lifecycle | Never | Audit trail, syncing "new since last run" |
processedAt / processed_at | When the order was processed; "might not match" the creation time | Yes: set on import, or updated by a backdating tool | The order date: order page, Orders list, analytics |
updatedAt / updated_at | When the order was last modified | Changes on every edit | Incremental syncs that need to catch edits |
closedAt / closed_at | Recorded when all items have been fulfilled or canceled; null if the order isn't closed | Set by Shopify | Measuring time to close an order |
cancelledAt / cancelled_at | When the order was canceled; null if it wasn't | Set when you cancel | Cancellation reporting |
The two that cause confusion are the first two. The rest are lifecycle timestamps that do what their names suggest.
Which date does Shopify show on your orders?
Shopify shows processed_at. The description of processedAt in Shopify's order creation input says plainly that this value is the date that appears on your orders and the one used in analytic reports.
That's why a backdated or imported order shows its original sale date on the order page and in the Orders list, even though its created_at is today. It's also why the default sort for the GraphQL orders query is PROCESSED_AT: when you list orders through the API without choosing a sort key, you get them in order-date order, not creation order.
A worked example makes the split concrete. Say a wholesale customer phoned in an order on May 13, and your team entered it on May 20 and backdated it:
| Value | |
|---|---|
createdAt | 2026-05-20T15:42:10-07:00 (when it was entered) |
processedAt | 2026-05-13T12:00:00-07:00 (when it was sold) |
| Order page and Orders list | May 13 |
| Analytics reports | Counted on May 13 |
created_at:>=2026-05-14 API search | Included (entered May 20) |
processed_at:>=2026-05-14 API search | Not included (sold May 13) |
Both dates are correct. They answer different questions: "when did we sell it?" and "when did Shopify find out?"
Can you change created_at or processed_at?
You can never change created_at, and you can change processed_at only in specific ways. Shopify documents createdAt as unchanged throughout an order's lifecycle, so anything that claims to edit the "created date" of an existing order is really changing something else, usually processedAt.
There are three ways processed_at gets a value other than the checkout moment:
- At creation, through an import or the API. Shopify's order creation input lets you set
processedAtto a date in the past when you're importing orders from an app or another platform. This is how migration tools bring over years of history with the right dates. - On an existing order, through a backdating app or script. This updates the order's processed date after the fact. We cover the methods and their trade-offs in how to backdate orders in Shopify.
- Never in the future. As of GraphQL Admin API version 2026-07, a future
processedAton order creation is clamped to the current time. Earlier versions return aPROCESSED_AT_INVALIDerror.
One developer detail worth knowing: the GraphQL orderUpdate mutation's input (OrderInput) doesn't include a processedAt field. It covers things like the email, note, tags, shipping address and PO number. So "update the order date" is not a one-line GraphQL mutation, which is part of why merchants end up using dedicated tools for it.
Payments have their own processed date too. The orderCreateManualPayment mutation accepts a processedAt that can be set in the past to match when the original transaction happened. If you're recording late payments, set that as well, or the payment and the order will tell different stories.
Which date do reports, exports and integrations use?
They don't all use the same one, and that's the most common source of "the date is wrong" tickets. Shopify's analytics follow processed_at. The admin CSV export is less clear, and third-party tools vary.
| Where you look | Date it follows | Confidence |
|---|---|---|
| Order page and Orders list | processed_at | Documented by Shopify |
| Shopify analytics reports | processed_at | Documented by Shopify |
GraphQL orders query, default sort | processed_at (PROCESSED_AT sort key) | Documented by Shopify |
| Admin CSV export, Created at column | Described as "when the order was completed by the customer"; an export app vendor reports it uses the creation timestamp | Test with one imported order |
| Accounting, ERP and analytics integrations | Whatever the vendor chose | Ask the vendor or test |
The CSV export gap
Shopify's export includes Created at, Paid at, Fulfilled at and Canceled at columns, but no column labeled as the processed date. Highview Apps, which makes an export app, reports that the native export fills Created at and Paid at from the creation timestamp, so imported orders show the import date. That matches what merchants describe, but it comes from a vendor rather than Shopify, so check it yourself: export one imported or backdated order and compare its Created at value with the date on the order page. If they differ, your export is showing created_at.
If you need the processed date in a spreadsheet, you have two options: an export app that includes the processed date field, or a short script against the Admin API that reads processedAt directly.
Integrations
Accounting and ERP connectors make their own choice. Some book a sale on the processed date, some on the creation date, some on the payment date. Before you import or backdate a batch of orders, find out which field your connector reads and whether it re-syncs when the date changes. A connector that already pulled an order may keep the first date it saw.
Which one should you use in your code or reports?
Use processed_at for anything about when sales happened, and created_at or updated_at for anything about when records changed. That one rule handles almost every case.
| Task | Use | Why |
|---|---|---|
| Revenue by day, week or month | processed_at | Matches Shopify's own analytics and the order page |
| Sales tax periods, month-end close | processed_at | It's the sale date, including corrected and imported orders |
| "Fetch every order added since my last sync" | created_at | Imported orders with old processed dates would otherwise be skipped |
| "Fetch every order changed since my last sync" | updated_at | Catches edits, refunds, tags and backdates |
| Time from order to fulfillment | processed_at to the fulfillment date | Starts the clock at the sale, not the data entry |
| Audit trail of when data entered Shopify | created_at | It can't be altered |
The sync case is the one that bites developers. If a nightly job pulls orders with processed_at:>=yesterday, an order imported today with a sale date of last March will never appear in it. Filter on created_at or updated_at for syncing, then group by processed_at for reporting.
Two practical API notes from Shopify's docs:
- Match the sort key to the filter. The
ordersquery supportscreated_at,processed_atandupdated_atfilters, andCREATED_AT,PROCESSED_ATandUPDATED_ATsort keys. Shopify recommends a sort key that matches the field you search on for performance. - Mind the 60-day window. By default the API only returns orders from the last 60 days. Older orders need the
read_all_ordersscope, which Shopify grants per app. A report that silently stops at 60 days is usually this.
Also note that the REST Admin API has been a legacy API since October 1, 2024, and new public apps must use GraphQL. Existing scripts that read processed_at from REST still see the same value, but new work should use the GraphQL field names (processedAt, createdAt).
Timezones: why both dates can look a day off
Both fields are full timestamps with a timezone offset, not calendar dates. A value like 2026-05-13T00:00:00Z (midnight UTC) is still May 12 in the evening for a store in Los Angeles or New York. If an import or script writes midnight UTC, the order can land on the previous day in your store's timezone.
The fix is to always write an explicit time and offset in your store's timezone, ideally midday. 2026-05-13T12:00:00-07:00 stays on May 13 no matter how it's converted. The same applies when reading: convert timestamps to your store's timezone before grouping by day, or your daily totals won't match Shopify's.
How RetroOrder helps
When an order already in Shopify has the wrong order date, the field to fix is processed_at, and the admin has no way to edit it. RetroOrder adds Backdate with RetroOrder to the Orders page bulk actions. It updates the processed date Shopify shows, leaves createdAt alone (no app can change it), anchors each date to noon in your store's timezone so it doesn't slip a day, and works on orders older than 60 days. Line items, totals, taxes, the customer and fulfillment stay as they were. The free plan covers 10 backdated orders per calendar month, and RetroOrder Unlimited ($9.99/month, 14-day free trial) removes the limit.
Frequently asked questions
Which date does Shopify show on the order page, created_at or processed_at?
processed_at. Shopify's API documentation describes processedAt as the date that appears on your orders and that's used in analytics reports. For orders placed through checkout it's identical to created_at, so most merchants never notice there are two fields.
Can I change created_at on a Shopify order?
No. Shopify sets createdAt when the customer completes checkout and documents it as unchanged throughout the order's lifecycle. No app, script or support request can rewrite it. If you need an order to show a different date, the field to change is processedAt.
Can processed_at be a future date?
No. When creating orders through the GraphQL Admin API, versions 2026-07 and later clamp a future processedAt to the current time. Earlier versions reject it with a PROCESSED_AT_INVALID error. Past dates are allowed, which is how imported orders keep their original sale date.
Should my integration filter orders by created_at or processed_at?
Use processed_at for anything about when a sale happened, such as revenue by day or month, because that matches Shopify's own reports. Use created_at or updated_at for syncing, such as picking up every order that entered Shopify since your last run, because imported orders can have old processed dates.
Why does my order export show a different date than the order page?
The order page shows the processed date. The CSV export's Created at column is described as when the customer completed the order, and an export app vendor reports it uses the creation timestamp. For imported or backdated orders those two values differ, so the export shows the date the order entered Shopify.
Sources
- Shopify Admin GraphQL API: Order object
- Shopify Admin GraphQL API: OrderCreateOrderInput (processedAt)
- Shopify Admin GraphQL API: orders query
- Shopify Help Center: Exporting orders
- Shopify REST Admin API: Order resource (legacy notice, 60-day limit)
- Highview Apps: Why Shopify's order export doesn't have the correct Created At date