Account requests and optional payment

Record an application request and, only when intended, submit a separate legacy Stripe payment attempt for that record. The returned account_id identifies the application request. It does not mean a member account has been created.

TaskOperationAccess
Record an applicationCreate requestGuest; fixed deployment resource.
Attempt payment for an existing requestPayment attemptGuest; no record-owner check.

Example clients and synthetic values follow response conventions.

Request context and returned fields

Both actions permit guest access without a member token or required resource header. They replace resource context with one fixed deployment resource; sending a resource public key does not select another account-request resource. The deployment resource must exist for request-event handling. No account-owner check is added by these actions. Protect record selection in your trusted application; an account-request ID is not proof of ownership.

FieldType / presenceMeaning
account_idstored integer; HTTP 200AccountRequests record ID, retained between these two calls. No member/session/entitlement is created by the response.
messagestring; HTTP 200Operation-specific acknowledgement shown in its example; not proof of downstream completion or settlement.
errorboolean true; field-validation failureDirect validation response, distinct from string API error codes.
error_fieldsobject; field-validation failureDynamic field-name → validator-message strings; messages can vary, and the last message for a repeated field wins. Create keys are first_name, last_name, company_name, job_title, email, plan, number_of_websites and conditionally stripe_token; payment keys are account_id and stripe_token.
errorstring; handled body/record/action failureCode described in operation recovery.
error_descriptionstring; string-code errorHuman explanation; no provider object is returned.
req_guidstring; string-code errorRequest correlation value. Direct field-validation responses do not add it unless debug metadata does.

Other optional debug metadata follows response conventions.

Record an application request

POST /api/v1/account-requests

Save submitted contact/application fields, then attempt an account_request queue event. There is no duplicate guard or idempotency key. Repeating the submission can create another record.

Before you call

Use the account-request context. The action saves an AccountRequests record with server timestamps and REMOTE_ADDR IP, then attempts a queue event carrying its ID, email, plan and fixed resource ID. Queue transmission failure can be swallowed; an acknowledgement does not prove delivery or downstream processing. A later failure can leave the saved record in place.

No active email call or account/user provisioning occurs in this action. An optional Stripe token is stored here, with no provider call. Plan is only a required string: there is no service-pricing-plan lookup or closed enum validation.

Request

Content-Type: application/json; truthy decoded body required. Submit an object with these fields. Presence validators run before storage sanitization; there is no explicit strict JSON-type or length validation for the required strings.

NameLocationType / requirementMeaning / constraint
first_nameJSONrequired stringContact name; string/trim sanitization when saved.
last_nameJSONrequired stringContact surname; string/trim sanitization when saved.
company_nameJSONrequired stringCompany label; string/trim sanitization.
job_titleJSONrequired stringContact role; string/trim sanitization.
emailJSONrequired valid emailTrimmed for validation; email/trim/lower sanitization for storage.
planJSONrequired stringRequested label; trimmed/string sanitized, with no Pricing ID or accepted-plan lookup. pro and pro-early are recognized by the separate payment price branch.
number_of_websitesJSONoptional number, default 1 on omission/nullPresence and between 1–10 validation, then integer-filter storage. Supply an integer; no strict integer JSON-type validation.
phone_numberJSONoptional string / nullString/trim sanitization; no phone format validation.
terms_and_conditionsJSONoptional Boolean-filter value, default falseStored boolean; no active required/true acceptance validation. Example supplies true explicitly.
stripe_tokenJSONoptional supplied stringOnly truthy supplied values are validated/stored; no charge here. Omit when only recording the request.

Result

HTTP 200 JSON fields use the request-result table. account_id identifies the saved application record; message acknowledges the application path. No user/session, provider result or public record details are serialized.

Example: Keep the new request ID without implying provisioning

Submit an application for two websites without a payment token. Retain synthetic account_id 8001 as the request ID only.

curl -X POST "${WALLKIT_API_BASE}/api/v1/account-requests" \
  -H "Content-Type: application/json" \
  --data-raw '{"first_name": "Alex", "last_name": "Reader", "company_name": "Example Media", "job_title": "Publisher", "email": "reader@example.com", "plan": "pro-early", "number_of_websites": 2, "terms_and_conditions": true}'
const response = await fetch(`${process.env.WALLKIT_API_BASE}/api/v1/account-requests`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"first_name": "Alex", "last_name": "Reader", "company_name": "Example Media", "job_title": "Publisher", "email": "reader@example.com", "plan": "pro-early", "number_of_websites": 2, "terms_and_conditions": true})
});
console.log(response.status, await response.json());
import os, json
from urllib.request import Request, urlopen
from urllib.error import HTTPError

body = {'first_name': 'Alex', 'last_name': 'Reader', 'company_name': 'Example Media', 'job_title': 'Publisher', 'email': 'reader@example.com', 'plan': 'pro-early', 'number_of_websites': 2, 'terms_and_conditions': True}
request = Request(os.environ["WALLKIT_API_BASE"] + "/api/v1/account-requests",
    data=json.dumps(body).encode("utf-8"),
    headers={"Content-Type": "application/json"}, method="POST")
try:
    with urlopen(request) as response:
        print(response.status, json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))

Synthetic HTTP 200 excerpt:

{
  "account_id": 8001,
  "message": "Thank you! Wallkit Limited Beta: Application Successful!"
}

The saved request may be available even if later processing fails; this result does not sign the person in.

Consequential alternate

If record/event-stage handling throws a caught exception, HTTP 409 excerpt (other response metadata omitted):

{
  "error": "account_request_create_error",
  "error_description": "Error creating account request"
}

A record may already have been saved. Do not automatically submit again; ask integration owner to reconcile the attempt.

Recovery

HTTP statusAPI code / shapeCauseNext action
406incorrect_data; Body must be json formatNo truthy decoded JSON body.Send a JSON object with the required fields and correct media type.
409error:true plus error_fieldsRequired fields, email or website range validation fails.Correct the named fields; treat messages as dynamic validation text.
409account_request_create_errorSave or subsequent caught handling error.Reconcile existing request state before resubmitting; input validation is not the only failure point.

Next task

Keep the request acknowledgement. Only when a payment is intended for this record, read the separate payment attempt and its duplicate/partial-write behavior first.

Attempt payment for an existing request

POST /api/v1/account-requests-payment

Create a Stripe customer and charge for an existing account-request record. The action has no already-paid guard or idempotency key: retrying can create another customer and charge.

Before you call

Use the account-request context and the account_id returned by request creation. The action checks required input presence, then selects AccountRequests directly by the supplied account_id; it has no ownership/resource check or explicit numeric validation. Supply only the intended integer record ID.

Provide an existing provider token for this deployment’s Stripe integration. The server uses its ACCOUNT_REQUST_STRIPE_PRIVATE_KEY configuration (spelling preserved); that key determines provider account/mode. This action does not select the resource’s default payment provider or payments_in_live_mode and accepts no mode flag.

It first replaces/stores stripe_token and refreshes the record. A failed token save is logged without stopping, so the refreshed token can be the previously stored value. It then creates a Stripe customer with stored email/token, calculates amount and creates a charge. Final customer/charge persistence failure is also logged without stopping. Provider writes can precede local failure; no enclosing transaction, rollback or refund guarantee. No active email/payment-event call or Purchases/Transactions/membership creation occurs here.

Request

Content-Type: application/json; truthy decoded body required.

NameLocationType / requirementMeaning / constraint
account_idJSONrequired; supply integer record IDPresence validated, passed directly to record lookup without numeric sanitization or ownership proof. Use the account-request ID, not a user ID.
stripe_tokenJSONrequired supplied stringPresence validated then string sanitized for storage; provider source uses refreshed stored value. No local provider-token format check.

Charge amount is 19900 multiplied by the stored number_of_websites, passed without conversion, with currency USD. pro-early, pro and every other plan label currently select the same 19900 value. The action supplies no independent amount/unit validation; this documents the provider argument, not a universal Wallkit money unit or configurable service-plan price.

Result

HTTP 200 JSON fields use the request-result table. The acknowledgement follows provider customer/charge returns and attempted persistence. The action does not inspect charge status, paid/captured or settlement. Provider customer/charge objects and amount are not exposed in the result.

Example: Interpret the payment acknowledgement for request 8001

This scenario uses the request ID from the creation example and an obvious synthetic provider-token placeholder. A source-path acknowledgement assumes provider calls return without caught exceptions; the placeholder cannot perform a payment. With two stored websites, the charge argument amount is 39800 and currency USD.

curl -X POST "${WALLKIT_API_BASE}/api/v1/account-requests-payment" \
  -H "Content-Type: application/json" \
  --data-raw '{"account_id": 8001, "stripe_token": "SYNTHETIC_PROVIDER_TOKEN"}'
const response = await fetch(`${process.env.WALLKIT_API_BASE}/api/v1/account-requests-payment`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"account_id": 8001, "stripe_token": "SYNTHETIC_PROVIDER_TOKEN"})
});
console.log(response.status, await response.json());
import os, json
from urllib.request import Request, urlopen
from urllib.error import HTTPError

body = {'account_id': 8001, 'stripe_token': 'SYNTHETIC_PROVIDER_TOKEN'}
request = Request(os.environ["WALLKIT_API_BASE"] + "/api/v1/account-requests-payment",
    data=json.dumps(body).encode("utf-8"),
    headers={"Content-Type": "application/json"}, method="POST")
try:
    with urlopen(request) as response:
        print(response.status, json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))

Synthetic HTTP 200 excerpt:

{
  "account_id": 8001,
  "message": "Thank you! Wallkit Early Bird: Successfully Signed Up!"
}

Do not read the literal sign-up message as account provisioning, confirmed settlement or successful local persistence.

Consequential alternate

A caught provider or subsequent handling exception produces HTTP 409 excerpt (other response metadata omitted):

{
  "error": "account_request_payment_error",
  "error_description": "Error payment account request"
}

Token/customer/charge effects may already exist. Do not blindly retry: another attempt can create another charge.

Recovery

HTTP statusAPI code / shapeCauseNext action
406incorrect_data; Body must be json formatNo truthy decoded JSON body.Send the required JSON object with correct media type.
409error:true plus error_fieldsaccount_id or stripe_token missing/empty under presence validation.Supply the intended request ID and provider token; do not substitute member credentials.
404account_request_not_exists; Account request not foundRecord lookup returns no request.Check the ID against the saved application acknowledgement; do not create a new record automatically.
409account_request_payment_errorCaught provider/amount/handling exception.Ask integration owner to reconcile provider and local state before deciding on another attempt.
200Acknowledgement despite unchecked local-save failureProvider path returns but persistence can fail.Do not infer durable charge state from this response; reconcile through the integration owner.

Next task

Retain the acknowledgement and reconcile the intended payment outcome through the integration owner. Return to In-depth integration tasks for unrelated choices; this response establishes no content-access decision.

Full diagram

Use the arrow keys to scroll. Escape closes this view.

Search documentation

Enter at least 2 characters.

    ↑ ↓ move through results · Enter opens · Escape closes