Skip to main content

Intent Lifecycle

An intent tracks its own lifecycle — whether it has been used — not the outcome of the payment it created.

StatusMeaning
createdAwaiting fulfillment. Usable until expires_at.
fulfilledUsed to create a payment. Whether that payment succeeded is tracked on the payment, not here.
canceledCanceled before use. The client_secret no longer works.

fulfilled does not mean paid​

An intent becomes fulfilled the moment it is used to originate a payment — including when that payment is declined. The intent's job is to authorize the attempt, and it is done once the attempt is made.

Never treat "status": "fulfilled" as confirmation of a successful charge. To know whether you were paid, read the payment: Fetch Payment, or a payment_paid webhook.

Expiry​

Every intent expires one hour after it is created. expires_at is always set, and the window is fixed — it cannot be configured per intent.

Expiry is not a status. An intent past expires_at stays created, but it can no longer be fulfilled or canceled — both return a 400. Decide whether an intent is still usable from expires_at, not from status alone.

Because the clock starts at creation and not at the pay button, create the intent close to the moment the customer is ready to pay. See the on_initiating approach in Fulfill an Intent.

Read an intent​

Endpoint: GET /v1/payment_intents/{id}

Authentication: Secret key

GET /v1/payment_intents/{id}
curl https://api.moyasar.com/v1/payment_intents/{intent_id} \
-u sk_test_YOUR_SECRET_KEY:

The secret key is required because the response contains the client_secret. A publishable key gets 403.

Cancel an intent​

Endpoint: POST /v1/payment_intents/{id}/cancel

Authentication: Secret key

POST /v1/payment_intents/{id}/cancel
curl -X POST https://api.moyasar.com/v1/payment_intents/{intent_id}/cancel \
-u sk_test_YOUR_SECRET_KEY:

No request body is needed. The intent's status becomes canceled and its client_secret stops working.

Cancel when you know the checkout is over and you would rather the outstanding secret not be usable — the customer emptied their cart, the order was cancelled, or your backend priced the order again and needs a new intent for a different amount.

An intent that is already fulfilled, already canceled, or expired returns 400 with "type": "intent_not_cancelable". Expired intents need no cancellation; they are already unusable.

Quick reference​

OperationEndpointAuthAllowed when
CreatePOST /v1/payment_intentsSecret key—
FulfillPOST /v1/payment_intents/{id}/fulfillPublishable keycreated and not expired
FetchGET /v1/payment_intents/{id}Secret keyAlways
CancelPOST /v1/payment_intents/{id}/cancelSecret keycreated and not expired