You submitted. Days passed. Then App Store Connect went red: 1.0 Rejected, with the banner "3.0.0 Business: Preamble." Your stomach drops — that's a Business rejection, and you have in-app purchases, so something about your monetization must be wrong.
Then you open the message, and it's one sentence:
Specifically, can you confirm that YourApp Pro Lifetime — $129.99 is the intended price of your In-App Purchase product, YourApp Pro Lifetime?
That's it. No defect. No violated rule. No list of things to fix.
This is Apple's automated price-confirmation hold, and it is one of the most misread states in App Store Connect — because the UI screams Rejected while the content is just a question. This chapter is what the code means, exactly how to answer, and the one button that will surprise you.
TL;DR
3.0.0 Business: Preambleis not a finding. The.0.0means no numbered rule was cited. Apple is invoking the section's opening prose because there is no specific rule for "this price looks unusual."- The entire remedy is a reply in Resolution Center confirming the price is intentional. Apple's message says they will continue the review once they receive it.
- Your version will keep saying
Rejectedafter you reply. That is expected. The state only changes when Apple acts — or when you resubmit. - ⚠️ "Update Review" on the version page submits immediately. It is not a stage-then-send step. One click resubmits your app.
- Read your true state from the
irisAPI or theascCLI instead of inferring it from greyed-out buttons.
What the guideline code actually means
App Store Review Guidelines have exactly five top-level sections:
1. Safety 2. Performance 3. Business 4. Design 5. LegalRules nest beneath them: 3.1 Payments → 3.1.1 In-App Purchase → 3.1.1(a) Link to Other Purchase Methods. Any code you get decodes as section → rule → sub-rule.
Each section also opens with a few paragraphs of plain prose before the numbered rules begin. That intro is the preamble, and it states the section's philosophy.
So 3.0.0 decodes as:
3 → Business section
.0 → no specific rule
.0 → no specific sub-ruleX.0.0 is the "no numbered rule was broken" code. It means Apple is invoking the section's spirit precisely because you didn't violate anything in it.
Why the preamble, specifically
Section 3's preamble says pricing is your call, but that Apple won't distribute in-app purchases that are clear rip-offs — including this line:
"We'll reject expensive apps that try to cheat users with irrationally high prices." — App Store Review Guidelines, §3 preamble
There is no numbered rule implementing that sentence. It exists only in the preamble. So when Apple's automated tooling wants to sanity-check a price — typically a high one-time non-consumable, where a mistyped tier is a real risk — the preamble is the only thing it can cite.
That's the whole story. A trailing zero in the wrong place would produce a genuinely predatory price, so Apple asks before shipping it.
The reply that resolves it
Answer the literal question in the first sentence. Everything after is supporting credibility.
Hello,
Yes — I confirm that $129.99 (USD) is the intended price for the in-app purchase "YourApp Pro Lifetime" (
com.example.yourapp.pro.lifetime). It is not a typographical or configuration error.It is the one-time-payment option in a deliberate three-tier structure for the same content:
- YourApp Pro Monthly — $9.99 per month (1-week free trial)
- YourApp Pro Annual — $59.99 per year (1-week free trial)
- YourApp Pro Lifetime — $129.99, one time
The lifetime tier is priced at roughly two years of the annual plan, which is intentional for users who use the app across a multi-year period.
Customers cannot be charged unexpectedly: the paywall presents all three options side by side with live StoreKit pricing and the billing period clearly labeled ("one-time" for Lifetime) before any purchase, Restore Purchases is available, and a free tier requires no purchase at all.
Please proceed with the review.
A coherent pricing ladder is what makes "yes, intended" credible. $9.99/mo → $59.99/yr → $129.99 lifetime reads as deliberate. A lone $129.99 with no ladder around it reads like a typo — which is exactly why you got asked.
⚠️ The button that will surprise you
After you reply, your version still reads Rejected, and there is a tempting blue "Update Review" button on the version page.
It submits immediately. It is not a staging step, it does not merely mark the rejected item as addressed, and it does not wait for a second confirmation elsewhere. One click and your app is back in the queue.
Here is the state transition, captured before and after a single click:
BEFORE AFTER
version: REJECTED → WAITING_FOR_REVIEW
submission: UNRESOLVED_… → WAITING_FOR_REVIEW
submittedDate: (original) → (new timestamp)
items: 1 REJECTED + → all READY_FOR_REVIEW
4 READYReply, or resubmit? The honest answer
Both work. They differ in what they cost.
| Reply and wait | Click "Update Review" | |
|---|---|---|
| Mechanism | The one Apple's message names | A fresh submission |
| Timeline | Apple resumes on their side, typically 24–48h | Re-enters the queue, typically 24–48h |
| Risk | None — it's the prescribed path | The halted review restarts from the top |
| Best when | You replied recently | 24h+ of silence, or a weekend is about to swallow it |
The nuance worth understanding: Apple's message says the review "cannot proceed." That means it was halted early — a full human pass may not have happened yet. Resubmitting restarts that pass, which re-rolls the dice on findings unrelated to price (Guideline 4.3 spam, metadata, anything). That's not an argument against ever resubmitting; it's an argument against resubmitting impatiently, an hour after replying.
Apple's docs also note you can edit items in a submission once before resubmission. It's a limited resource. Don't spend it on an unchanged build out of restlessness.
Read the truth, don't infer it from the UI
The App Store Connect web UI is backed by an internal iris API, and read-only GETs authenticate with your existing session cookies. Open the JavaScript console on any App Store Connect page while logged in:
// 1. Your version's real state
fetch('/iris/v1/apps/<YOUR_APP_ID>/appStoreVersions?limit=5' +
'&fields[appStoreVersions]=versionString,appStoreState,appVersionState',
{headers:{Accept:'application/json'}})
.then(r => r.json()).then(j => console.log(j.data.map(d => d.attributes)));
// 2. Find the Resolution Center thread for that version
fetch('/iris/v1/resolutionCenterThreads?filter[appStoreVersion]=<VERSION_ID>',
{headers:{Accept:'application/json'}})
.then(r => r.json()).then(j => console.log(j.data.map(t => ({
id: t.id,
type: t.attributes.threadType, // REJECTION_REVIEW_SUBMISSION
canReply: t.attributes.canDeveloperAddNote,
lastMessage: t.attributes.lastMessageResponseDate,
}))));
// 3. Read the actual messages
fetch('/iris/v1/resolutionCenterThreads/<THREAD_ID>/resolutionCenterMessages?limit=50',
{headers:{Accept:'application/json'}})
.then(r => r.json()).then(j => console.log(j.data.map(m => ({
at: m.attributes.createdDate,
body: m.attributes.messageBody.replace(/<[^>]+>/g, ' '),
}))));Two quirks worth knowing: filter[app] is not a valid filter on resolutionCenterThreads (filter by appStoreVersion), and the submission's own lastUpdatedDate does not tick when you post a reply — messages are a separate object. Don't read that as a failed send; check the thread's lastMessageResponseDate instead.
Verify from the terminal instead
An App Store Connect API key authenticates through a completely different path than your browser session — so if you suspect a stale login is lying to you, this settles it. (Setup: see Appendix B of Chapter 3.)
asc review status --app <YOUR_APP_ID>
asc review doctor --app <YOUR_APP_ID> # explains what's blocking
asc review items list --submission <SUBMISSION_ID>review status returns the version state, the latest submission, and a nextAction. During a hold you'll see UNRESOLVED_ISSUES; once resubmitted, WAITING_FOR_REVIEW with nextAction: "Wait for App Store review outcome."
A watch script
Polling by hand gets old. This reports only what changed since the last run — no browser, no Apple ID, no 2FA:
#!/usr/bin/env bash
# review_watch.sh <APP_ID> — read-only; never submits anything.
set -euo pipefail
APP_ID="${1:?usage: review_watch.sh <APP_ID>}"
CACHE="${TMPDIR:-/tmp}/review_watch_$APP_ID.json"
NOW="$(asc review status --app "$APP_ID")"
read -r STATE SUB_STATE <<<"$(jq -r '[.version.state, .latestSubmission.state] | @tsv' <<<"$NOW")"
echo "version: $STATE | submission: $SUB_STATE"
if [[ -f "$CACHE" ]]; then
read -r P_STATE P_SUB <<<"$(jq -r '[.version.state, .latestSubmission.state] | @tsv' <"$CACHE")"
if [[ "$STATE" == "$P_STATE" && "$SUB_STATE" == "$P_SUB" ]]; then
echo "→ no change"
else
echo "*** CHANGED *** $P_STATE -> $STATE | $P_SUB -> $SUB_STATE"
fi
fi
printf '%s' "$NOW" >"$CACHE"An API key issued at the team level reads every app in the account, so one script covers your whole portfolio.
The states you'll see
| State | Meaning |
|---|---|
WAITING_FOR_REVIEW | Queued. Nothing to do. |
IN_REVIEW | Actively being reviewed. |
REJECTED / UNRESOLVED_ISSUES | Apple raised an issue or asked a question. Read the thread before acting. |
PENDING_DEVELOPER_RELEASE | Approved. Ship it. |
READY_FOR_DISTRIBUTION | Live. |
The critical row is the third: REJECTED does not distinguish "your app is broken" from "we'd like to confirm a number." Only the Resolution Center message tells you which.
Do NOT do these
- ❌ Change the price to make the question go away. You'd be answering a different question than the one asked, and editing a product mid-review complicates the submission. If the price is intentional, say so.
- ❌ Treat "Update Review" as a safe preview. It submits.
- ❌ Resubmit within hours of replying. Apple hasn't read it yet, and you restart a review that was halted before completing.
- ❌ Answer with a wall of context about your whole app. Guideline 3 threads reward precision, not enthusiasm.
- ❌ Assume silence means failure. 24 hours on a queued question is normal, not a signal.
Mini-exercise: classify your own hold
Before touching any button, answer these in writing:
- What's the full guideline code? If it ends in
.0.0, no numbered rule was cited — you're being asked, not told. - Does the message contain a question mark? A question means information is wanted. A defect report names what failed and how to reproduce it.
- Does it say "resubmit"? Apple's defect rejections say to make changes and resubmit. Information holds say they'll continue the review. Yours will say one or the other — go read it.
- What does
asc review statusreturn? Confirm the UI isn't showing you a stale page.
If the answers are ".0.0, yes, no, UNRESOLVED_ISSUES" — you're in this chapter. Reply, and give it a day.
Key Points
X.0.0means no numbered rule was cited. It's the mildest thing any section can hand you: a judgment call or a question, not a finding.- Section 3's preamble is the only place the "irrationally high prices" rule lives — which is why a price sanity-check has nowhere else to point.
- Answer the literal question in sentence one, show a coherent pricing ladder, and volunteer nothing else.
- "Update Review" submits immediately. It is not staging. Never infer ASC button semantics from whether a neighbouring button is greyed out.
REJECTEDin the UI is ambiguous by design. Read the Resolution Center thread — viairisif you want the raw truth — before you decide anything.- The public API can tell you your state, never Apple's question. Generic "resubmit if needed" advice from tooling is a hedge, not a recommendation.
- Replying and resubmitting are additive, not exclusive. The thread survives; reply first, resubmit later if it stalls.
App Store Connect makes a question look identical to a verdict, and that's a UI problem, not a you problem. If you got 3.0.0 Business: Preamble and panicked for a minute — everyone does. Next in the series: Code Signing Without Tears — certificates, profiles, and the .p8 key, the part of shipping iOS that actually deserves the anxiety.
Read next

Ultimate iOS Bootcamp: Master Swift & SwiftUI App THE HARD WAY
Ship your apps faster
When you're ready to publish your Swift app to the App Store, Simple App Shipper handles metadata, screenshots, TestFlight, and submissions — all in one place.
Try Simple App Shipper